mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 15:11:31 +00:00
[client] render: reduce software surface queue overhead
This commit is contained in:
@@ -1936,34 +1936,32 @@ static void swSurfaceDrawFill(LG_VideoSource source, int x, int y,
|
|||||||
int width, int height, uint32_t color)
|
int width, int height, uint32_t color)
|
||||||
{
|
{
|
||||||
LG_LOCK(g_state.videoSourceLock);
|
LG_LOCK(g_state.videoSourceLock);
|
||||||
if (!swSurfaceEventAdmitted(source))
|
const bool admitted = swSurfaceEventAdmitted(source);
|
||||||
{
|
const uint64_t generation = admitted ? atomic_load_explicit(
|
||||||
LG_UNLOCK(g_state.videoSourceLock);
|
&g_state.videoSource[source].generation, memory_order_acquire) : 0;
|
||||||
return;
|
LG_UNLOCK(g_state.videoSourceLock);
|
||||||
}
|
|
||||||
|
if (!admitted)
|
||||||
|
return;
|
||||||
|
|
||||||
const uint64_t generation = atomic_load_explicit(
|
|
||||||
&g_state.videoSource[source].generation, memory_order_acquire);
|
|
||||||
renderQueue_sourceSwSurfaceDrawFill(renderQueueSource(source), generation,
|
renderQueue_sourceSwSurfaceDrawFill(renderQueueSource(source), generation,
|
||||||
x, y, width, height, color);
|
x, y, width, height, color);
|
||||||
LG_UNLOCK(g_state.videoSourceLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swSurfaceDrawBitmap(LG_VideoSource source, bool topDown,
|
static void swSurfaceDrawBitmap(LG_VideoSource source, bool topDown,
|
||||||
int x, int y, int width, int height, int stride, const void * data)
|
int x, int y, int width, int height, int stride, const void * data)
|
||||||
{
|
{
|
||||||
LG_LOCK(g_state.videoSourceLock);
|
LG_LOCK(g_state.videoSourceLock);
|
||||||
if (!swSurfaceEventAdmitted(source))
|
const bool admitted = swSurfaceEventAdmitted(source);
|
||||||
{
|
const uint64_t generation = admitted ? atomic_load_explicit(
|
||||||
LG_UNLOCK(g_state.videoSourceLock);
|
&g_state.videoSource[source].generation, memory_order_acquire) : 0;
|
||||||
return;
|
LG_UNLOCK(g_state.videoSourceLock);
|
||||||
}
|
|
||||||
|
if (!admitted)
|
||||||
|
return;
|
||||||
|
|
||||||
const uint64_t generation = atomic_load_explicit(
|
|
||||||
&g_state.videoSource[source].generation, memory_order_acquire);
|
|
||||||
renderQueue_sourceSwSurfaceDrawBitmap(renderQueueSource(source), generation,
|
renderQueue_sourceSwSurfaceDrawBitmap(renderQueueSource(source), generation,
|
||||||
x, y, width, height, stride, data, topDown);
|
x, y, width, height, stride, data, topDown);
|
||||||
LG_UNLOCK(g_state.videoSourceLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swSurfacePointer(LG_VideoSource source,
|
static void swSurfacePointer(LG_VideoSource source,
|
||||||
|
|||||||
@@ -22,13 +22,123 @@
|
|||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/ll.h"
|
#include "common/locking.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
struct ll * l_renderQueue = NULL;
|
typedef struct RenderCommand
|
||||||
|
{
|
||||||
|
struct RenderCommand * next;
|
||||||
|
|
||||||
|
RenderQueueSource source;
|
||||||
|
uint64_t generation;
|
||||||
|
uint64_t transitionSerial;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SW_SURFACE_OP_CONFIGURE_TRANSITION,
|
||||||
|
SW_SURFACE_OP_DRAW_FILL,
|
||||||
|
SW_SURFACE_OP_DRAW_BITMAP,
|
||||||
|
SURFACE_OP_FORMAT,
|
||||||
|
CURSOR_OP_STATE,
|
||||||
|
CURSOR_OP_IMAGE,
|
||||||
|
CURSOR_OP_COLOR_TRANSFORM,
|
||||||
|
CURSOR_OP_WHITE_LEVEL,
|
||||||
|
SOURCE_OP_TRANSITION,
|
||||||
|
}
|
||||||
|
op;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
}
|
||||||
|
swSurfaceConfigureTransition;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
int width, height;
|
||||||
|
uint32_t color;
|
||||||
|
}
|
||||||
|
swSurfaceDrawFill;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int x , y;
|
||||||
|
int width, height;
|
||||||
|
int stride;
|
||||||
|
uint8_t * data;
|
||||||
|
bool topDown;
|
||||||
|
}
|
||||||
|
swSurfaceDrawBitmap;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
LG_RendererFormat format;
|
||||||
|
bool rendererSupportsNativeHDR;
|
||||||
|
}
|
||||||
|
surfaceFormat;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool visible;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int hx;
|
||||||
|
int hy;
|
||||||
|
}
|
||||||
|
cursorState;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
LG_RendererCursor type;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int pitch;
|
||||||
|
uint8_t * data;
|
||||||
|
}
|
||||||
|
cursorImage;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
LGColorTransform * data;
|
||||||
|
}
|
||||||
|
cursorColorTransform;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32_t value;
|
||||||
|
}
|
||||||
|
cursorWhiteLevel;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool swSurface;
|
||||||
|
}
|
||||||
|
sourceTransition;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
RenderCommand;
|
||||||
|
|
||||||
|
typedef enum RenderQueueInvalidate
|
||||||
|
{
|
||||||
|
RENDER_QUEUE_INVALIDATE_NONE,
|
||||||
|
RENDER_QUEUE_INVALIDATE_PARTIAL,
|
||||||
|
RENDER_QUEUE_INVALIDATE_FULL,
|
||||||
|
}
|
||||||
|
RenderQueueInvalidate;
|
||||||
|
|
||||||
|
static RenderCommand * l_renderQueueHead;
|
||||||
|
static RenderCommand * l_renderQueueTail;
|
||||||
|
static LG_Lock l_renderQueueLock;
|
||||||
|
static bool l_renderQueueInitialized;
|
||||||
|
static RenderQueueInvalidate l_renderQueueInvalidate;
|
||||||
|
|
||||||
static bool l_showSwSurface;
|
static bool l_showSwSurface;
|
||||||
static bool l_surfaceFormatValid;
|
static bool l_surfaceFormatValid;
|
||||||
static bool l_rendererSupportsNativeHDR;
|
static bool l_rendererSupportsNativeHDR;
|
||||||
@@ -136,10 +246,6 @@ static void freeCommand(RenderCommand * cmd)
|
|||||||
{
|
{
|
||||||
switch (cmd->op)
|
switch (cmd->op)
|
||||||
{
|
{
|
||||||
case SW_SURFACE_OP_DRAW_BITMAP:
|
|
||||||
free(cmd->swSurfaceDrawBitmap.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CURSOR_OP_IMAGE:
|
case CURSOR_OP_IMAGE:
|
||||||
free(cmd->cursorImage.data);
|
free(cmd->cursorImage.data);
|
||||||
break;
|
break;
|
||||||
@@ -155,6 +261,51 @@ static void freeCommand(RenderCommand * cmd)
|
|||||||
free(cmd);
|
free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool queueCommand(RenderCommand * cmd,
|
||||||
|
RenderQueueInvalidate invalidate)
|
||||||
|
{
|
||||||
|
bool wake = false;
|
||||||
|
cmd->next = NULL;
|
||||||
|
|
||||||
|
LG_LOCK(l_renderQueueLock);
|
||||||
|
if (l_renderQueueTail)
|
||||||
|
l_renderQueueTail->next = cmd;
|
||||||
|
else
|
||||||
|
l_renderQueueHead = cmd;
|
||||||
|
l_renderQueueTail = cmd;
|
||||||
|
|
||||||
|
if (invalidate > l_renderQueueInvalidate)
|
||||||
|
{
|
||||||
|
l_renderQueueInvalidate = invalidate;
|
||||||
|
wake = true;
|
||||||
|
}
|
||||||
|
LG_UNLOCK(l_renderQueueLock);
|
||||||
|
return wake;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wakeQueue(RenderQueueInvalidate invalidate, bool wake)
|
||||||
|
{
|
||||||
|
if (wake)
|
||||||
|
app_invalidateWindow(invalidate == RENDER_QUEUE_INVALIDATE_FULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enqueueCommand(RenderCommand * cmd,
|
||||||
|
RenderQueueInvalidate invalidate)
|
||||||
|
{
|
||||||
|
wakeQueue(invalidate, queueCommand(cmd, invalidate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static RenderCommand * detachCommands(void)
|
||||||
|
{
|
||||||
|
LG_LOCK(l_renderQueueLock);
|
||||||
|
RenderCommand * head = l_renderQueueHead;
|
||||||
|
l_renderQueueHead = NULL;
|
||||||
|
l_renderQueueTail = NULL;
|
||||||
|
l_renderQueueInvalidate = RENDER_QUEUE_INVALIDATE_NONE;
|
||||||
|
LG_UNLOCK(l_renderQueueLock);
|
||||||
|
return head;
|
||||||
|
}
|
||||||
|
|
||||||
static void setCommandSource(RenderCommand * cmd, RenderQueueSource source,
|
static void setCommandSource(RenderCommand * cmd, RenderQueueSource source,
|
||||||
uint64_t generation)
|
uint64_t generation)
|
||||||
{
|
{
|
||||||
@@ -231,7 +382,9 @@ static void updateSurfaceFormat(void)
|
|||||||
|
|
||||||
void renderQueue_init(void)
|
void renderQueue_init(void)
|
||||||
{
|
{
|
||||||
l_renderQueue = ll_new();
|
l_renderQueueHead = NULL;
|
||||||
|
l_renderQueueTail = NULL;
|
||||||
|
l_renderQueueInvalidate = RENDER_QUEUE_INVALIDATE_NONE;
|
||||||
l_showSwSurface = false;
|
l_showSwSurface = false;
|
||||||
l_surfaceFormatValid = false;
|
l_surfaceFormatValid = false;
|
||||||
l_rendererSupportsNativeHDR = false;
|
l_rendererSupportsNativeHDR = false;
|
||||||
@@ -249,13 +402,15 @@ void renderQueue_init(void)
|
|||||||
for (int i = 0; i < RENDER_QUEUE_SOURCE_COUNT; ++i)
|
for (int i = 0; i < RENDER_QUEUE_SOURCE_COUNT; ++i)
|
||||||
atomic_store_explicit(&l_sourceGeneration[i], 0, memory_order_relaxed);
|
atomic_store_explicit(&l_sourceGeneration[i], 0, memory_order_relaxed);
|
||||||
atomic_store_explicit(&l_transitionSerial, 0, memory_order_relaxed);
|
atomic_store_explicit(&l_transitionSerial, 0, memory_order_relaxed);
|
||||||
|
LG_LOCK_INIT(l_renderQueueLock);
|
||||||
LG_LOCK_INIT(l_sourceLock);
|
LG_LOCK_INIT(l_sourceLock);
|
||||||
LG_LOCK_INIT(l_transitionLock);
|
LG_LOCK_INIT(l_transitionLock);
|
||||||
|
l_renderQueueInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_free(void)
|
void renderQueue_free(void)
|
||||||
{
|
{
|
||||||
if (!l_renderQueue)
|
if (!l_renderQueueInitialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
renderQueue_clear();
|
renderQueue_clear();
|
||||||
@@ -266,17 +421,21 @@ void renderQueue_free(void)
|
|||||||
l_cursor[i].data = NULL;
|
l_cursor[i].data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ll_free(l_renderQueue);
|
l_renderQueueInitialized = false;
|
||||||
l_renderQueue = NULL;
|
LG_LOCK_FREE(l_renderQueueLock);
|
||||||
LG_LOCK_FREE(l_sourceLock);
|
LG_LOCK_FREE(l_sourceLock);
|
||||||
LG_LOCK_FREE(l_transitionLock);
|
LG_LOCK_FREE(l_transitionLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_clear(void)
|
void renderQueue_clear(void)
|
||||||
{
|
{
|
||||||
RenderCommand * cmd;
|
RenderCommand * cmd = detachCommands();
|
||||||
while(ll_shift(l_renderQueue, (void **)&cmd))
|
while(cmd)
|
||||||
|
{
|
||||||
|
RenderCommand * next = cmd->next;
|
||||||
freeCommand(cmd);
|
freeCommand(cmd);
|
||||||
|
cmd = next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_setSourceFns(RenderQueueSourcePrepareFn prepare,
|
void renderQueue_setSourceFns(RenderQueueSourcePrepareFn prepare,
|
||||||
@@ -354,19 +513,13 @@ static uint64_t enqueueTransition(RenderCommand * cmd,
|
|||||||
const uint64_t serial = atomic_load_explicit(
|
const uint64_t serial = atomic_load_explicit(
|
||||||
&l_transitionSerial, memory_order_relaxed) + 1;
|
&l_transitionSerial, memory_order_relaxed) + 1;
|
||||||
cmd->transitionSerial = serial;
|
cmd->transitionSerial = serial;
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
const bool wake = queueCommand(cmd, RENDER_QUEUE_INVALIDATE_FULL);
|
||||||
{
|
|
||||||
LG_UNLOCK(l_transitionLock);
|
|
||||||
free(cmd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
atomic_store_explicit(
|
atomic_store_explicit(
|
||||||
&l_transitionSerial, serial, memory_order_release);
|
&l_transitionSerial, serial, memory_order_release);
|
||||||
if (publishedSerial)
|
if (publishedSerial)
|
||||||
atomic_store_explicit(publishedSerial, serial, memory_order_release);
|
atomic_store_explicit(publishedSerial, serial, memory_order_release);
|
||||||
LG_UNLOCK(l_transitionLock);
|
LG_UNLOCK(l_transitionLock);
|
||||||
|
wakeQueue(RENDER_QUEUE_INVALIDATE_FULL, wake);
|
||||||
app_invalidateWindow(true);
|
|
||||||
return serial;
|
return serial;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -431,13 +584,7 @@ void renderQueue_sourceSwSurfaceDrawFill(RenderQueueSource source,
|
|||||||
cmd->swSurfaceDrawFill.width = width;
|
cmd->swSurfaceDrawFill.width = width;
|
||||||
cmd->swSurfaceDrawFill.height = height;
|
cmd->swSurfaceDrawFill.height = height;
|
||||||
cmd->swSurfaceDrawFill.color = color;
|
cmd->swSurfaceDrawFill.color = color;
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_PARTIAL);
|
||||||
{
|
|
||||||
free(cmd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_invalidateWindow(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_sourceSwSurfaceDrawBitmap(RenderQueueSource source,
|
void renderQueue_sourceSwSurfaceDrawBitmap(RenderQueueSource source,
|
||||||
@@ -462,32 +609,37 @@ void renderQueue_sourceSwSurfaceDrawBitmap(RenderQueueSource source,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((size_t)height > SIZE_MAX / (size_t)stride)
|
if (width > stride / 4)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Software surface bitmap stride is too small: "
|
||||||
|
"width: %d, stride: %d", width, stride);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t rowSize = (size_t)width * 4;
|
||||||
|
if ((size_t)height > (SIZE_MAX - sizeof(RenderCommand)) / rowSize)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Software surface bitmap size overflows: "
|
DEBUG_ERROR("Software surface bitmap size overflows: "
|
||||||
"height: %d, stride: %d",
|
"width: %d, height: %d", width, height);
|
||||||
height, stride);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t size = (size_t)height * (size_t)stride;
|
const size_t size = (size_t)height * rowSize;
|
||||||
RenderCommand * cmd = malloc(sizeof(*cmd));
|
RenderCommand * cmd = malloc(sizeof(*cmd) + size);
|
||||||
if (!cmd)
|
if (!cmd)
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to allocate software surface bitmap command");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t * copy = malloc(size);
|
|
||||||
if (!copy)
|
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to allocate %zu bytes for software surface bitmap",
|
DEBUG_ERROR("Failed to allocate %zu bytes for software surface bitmap",
|
||||||
size);
|
size);
|
||||||
free(cmd);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(copy, data, size);
|
uint8_t * copy = (uint8_t *)(cmd + 1);
|
||||||
|
if ((size_t)stride == rowSize)
|
||||||
|
memcpy(copy, data, size);
|
||||||
|
else
|
||||||
|
for(int row = 0; row < height; ++row)
|
||||||
|
memcpy(copy + (size_t)row * rowSize,
|
||||||
|
(const uint8_t *)data + (size_t)row * stride, rowSize);
|
||||||
|
|
||||||
setCommandSource(cmd, source, generation);
|
setCommandSource(cmd, source, generation);
|
||||||
cmd->op = SW_SURFACE_OP_DRAW_BITMAP;
|
cmd->op = SW_SURFACE_OP_DRAW_BITMAP;
|
||||||
@@ -495,17 +647,10 @@ void renderQueue_sourceSwSurfaceDrawBitmap(RenderQueueSource source,
|
|||||||
cmd->swSurfaceDrawBitmap.y = y;
|
cmd->swSurfaceDrawBitmap.y = y;
|
||||||
cmd->swSurfaceDrawBitmap.width = width;
|
cmd->swSurfaceDrawBitmap.width = width;
|
||||||
cmd->swSurfaceDrawBitmap.height = height;
|
cmd->swSurfaceDrawBitmap.height = height;
|
||||||
cmd->swSurfaceDrawBitmap.stride = stride;
|
cmd->swSurfaceDrawBitmap.stride = (int)rowSize;
|
||||||
cmd->swSurfaceDrawBitmap.data = copy;
|
cmd->swSurfaceDrawBitmap.data = copy;
|
||||||
cmd->swSurfaceDrawBitmap.topDown = topDown;
|
cmd->swSurfaceDrawBitmap.topDown = topDown;
|
||||||
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_PARTIAL);
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
|
||||||
{
|
|
||||||
freeCommand(cmd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_invalidateWindow(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_sourceSurfaceFormat(RenderQueueSource source,
|
void renderQueue_sourceSurfaceFormat(RenderQueueSource source,
|
||||||
@@ -524,13 +669,7 @@ void renderQueue_sourceSurfaceFormat(RenderQueueSource source,
|
|||||||
cmd->surfaceFormat.format = format;
|
cmd->surfaceFormat.format = format;
|
||||||
cmd->surfaceFormat.rendererSupportsNativeHDR =
|
cmd->surfaceFormat.rendererSupportsNativeHDR =
|
||||||
rendererSupportsNativeHDR;
|
rendererSupportsNativeHDR;
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_FULL);
|
||||||
{
|
|
||||||
free(cmd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_invalidateWindow(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_sourceCursorState(RenderQueueSource source,
|
void renderQueue_sourceCursorState(RenderQueueSource source,
|
||||||
@@ -550,8 +689,7 @@ void renderQueue_sourceCursorState(RenderQueueSource source,
|
|||||||
cmd->cursorState.y = y;
|
cmd->cursorState.y = y;
|
||||||
cmd->cursorState.hx = hx;
|
cmd->cursorState.hx = hx;
|
||||||
cmd->cursorState.hy = hy;
|
cmd->cursorState.hy = hy;
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_NONE);
|
||||||
free(cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_sourceCursorImage(RenderQueueSource source,
|
void renderQueue_sourceCursorImage(RenderQueueSource source,
|
||||||
@@ -572,8 +710,10 @@ void renderQueue_sourceCursorImage(RenderQueueSource source,
|
|||||||
cmd->cursorImage.height = height;
|
cmd->cursorImage.height = height;
|
||||||
cmd->cursorImage.pitch = pitch;
|
cmd->cursorImage.pitch = pitch;
|
||||||
cmd->cursorImage.data = NULL;
|
cmd->cursorImage.data = NULL;
|
||||||
if (!copyCursorImage(cmd, data) || !ll_push(l_renderQueue, cmd))
|
if (!copyCursorImage(cmd, data))
|
||||||
freeCommand(cmd);
|
freeCommand(cmd);
|
||||||
|
else
|
||||||
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_sourceCursorColorTransform(RenderQueueSource source,
|
void renderQueue_sourceCursorColorTransform(RenderQueueSource source,
|
||||||
@@ -597,8 +737,7 @@ void renderQueue_sourceCursorColorTransform(RenderQueueSource source,
|
|||||||
setCommandSource(cmd, source, generation);
|
setCommandSource(cmd, source, generation);
|
||||||
cmd->op = CURSOR_OP_COLOR_TRANSFORM;
|
cmd->op = CURSOR_OP_COLOR_TRANSFORM;
|
||||||
cmd->cursorColorTransform.data = copy;
|
cmd->cursorColorTransform.data = copy;
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_NONE);
|
||||||
freeCommand(cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQueue_sourceCursorWhiteLevel(RenderQueueSource source,
|
void renderQueue_sourceCursorWhiteLevel(RenderQueueSource source,
|
||||||
@@ -614,8 +753,7 @@ void renderQueue_sourceCursorWhiteLevel(RenderQueueSource source,
|
|||||||
setCommandSource(cmd, source, generation);
|
setCommandSource(cmd, source, generation);
|
||||||
cmd->op = CURSOR_OP_WHITE_LEVEL;
|
cmd->op = CURSOR_OP_WHITE_LEVEL;
|
||||||
cmd->cursorWhiteLevel.value = sdrWhiteLevel;
|
cmd->cursorWhiteLevel.value = sdrWhiteLevel;
|
||||||
if (!ll_push(l_renderQueue, cmd))
|
enqueueCommand(cmd, RENDER_QUEUE_INVALIDATE_NONE);
|
||||||
free(cmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void applyCursor(RenderQueueSource source, uint64_t generation)
|
static void applyCursor(RenderQueueSource source, uint64_t generation)
|
||||||
@@ -692,9 +830,10 @@ static bool prepareSourceTransition(const RenderCommand * cmd)
|
|||||||
|
|
||||||
void renderQueue_process(void)
|
void renderQueue_process(void)
|
||||||
{
|
{
|
||||||
RenderCommand * cmd;
|
RenderCommand * cmd = detachCommands();
|
||||||
while(ll_shift(l_renderQueue, (void **)&cmd))
|
while(cmd)
|
||||||
{
|
{
|
||||||
|
RenderCommand * next = cmd->next;
|
||||||
const bool transition = transitionCommand(cmd);
|
const bool transition = transitionCommand(cmd);
|
||||||
if (transition)
|
if (transition)
|
||||||
LG_LOCK(l_transitionLock);
|
LG_LOCK(l_transitionLock);
|
||||||
@@ -706,6 +845,7 @@ void renderQueue_process(void)
|
|||||||
if (transition)
|
if (transition)
|
||||||
LG_UNLOCK(l_transitionLock);
|
LG_UNLOCK(l_transitionLock);
|
||||||
freeCommand(cmd);
|
freeCommand(cmd);
|
||||||
|
cmd = next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,8 +876,6 @@ void renderQueue_process(void)
|
|||||||
cmd->swSurfaceDrawBitmap.width , cmd->swSurfaceDrawBitmap.height,
|
cmd->swSurfaceDrawBitmap.width , cmd->swSurfaceDrawBitmap.height,
|
||||||
cmd->swSurfaceDrawBitmap.stride, cmd->swSurfaceDrawBitmap.data,
|
cmd->swSurfaceDrawBitmap.stride, cmd->swSurfaceDrawBitmap.data,
|
||||||
cmd->swSurfaceDrawBitmap.topDown);
|
cmd->swSurfaceDrawBitmap.topDown);
|
||||||
free(cmd->swSurfaceDrawBitmap.data);
|
|
||||||
cmd->swSurfaceDrawBitmap.data = NULL;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SURFACE_OP_FORMAT:
|
case SURFACE_OP_FORMAT:
|
||||||
@@ -851,6 +989,7 @@ void renderQueue_process(void)
|
|||||||
if (transition)
|
if (transition)
|
||||||
LG_UNLOCK(l_transitionLock);
|
LG_UNLOCK(l_transitionLock);
|
||||||
freeCommand(cmd);
|
freeCommand(cmd);
|
||||||
|
cmd = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common/ll.h"
|
|
||||||
#include "interface/renderer.h"
|
#include "interface/renderer.h"
|
||||||
|
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
@@ -38,100 +37,6 @@ typedef void (*RenderQueueSourceAppliedFn)(void * opaque,
|
|||||||
typedef bool (*RenderQueueSourcePrepareFn)(void * opaque,
|
typedef bool (*RenderQueueSourcePrepareFn)(void * opaque,
|
||||||
RenderQueueSource source, uint64_t generation, uint64_t serial);
|
RenderQueueSource source, uint64_t generation, uint64_t serial);
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
RenderQueueSource source;
|
|
||||||
uint64_t generation;
|
|
||||||
uint64_t transitionSerial;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
SW_SURFACE_OP_CONFIGURE_TRANSITION,
|
|
||||||
SW_SURFACE_OP_DRAW_FILL,
|
|
||||||
SW_SURFACE_OP_DRAW_BITMAP,
|
|
||||||
SURFACE_OP_FORMAT,
|
|
||||||
CURSOR_OP_STATE,
|
|
||||||
CURSOR_OP_IMAGE,
|
|
||||||
CURSOR_OP_COLOR_TRANSFORM,
|
|
||||||
CURSOR_OP_WHITE_LEVEL,
|
|
||||||
SOURCE_OP_TRANSITION,
|
|
||||||
}
|
|
||||||
op;
|
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int width, height;
|
|
||||||
}
|
|
||||||
swSurfaceConfigureTransition;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
int width, height;
|
|
||||||
uint32_t color;
|
|
||||||
}
|
|
||||||
swSurfaceDrawFill;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
int x , y;
|
|
||||||
int width, height;
|
|
||||||
int stride;
|
|
||||||
uint8_t * data;
|
|
||||||
bool topDown;
|
|
||||||
}
|
|
||||||
swSurfaceDrawBitmap;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
LG_RendererFormat format;
|
|
||||||
bool rendererSupportsNativeHDR;
|
|
||||||
}
|
|
||||||
surfaceFormat;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool visible;
|
|
||||||
int x;
|
|
||||||
int y;
|
|
||||||
int hx;
|
|
||||||
int hy;
|
|
||||||
}
|
|
||||||
cursorState;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
LG_RendererCursor type;
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
int pitch;
|
|
||||||
uint8_t * data;
|
|
||||||
}
|
|
||||||
cursorImage;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
LGColorTransform * data;
|
|
||||||
}
|
|
||||||
cursorColorTransform;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32_t value;
|
|
||||||
}
|
|
||||||
cursorWhiteLevel;
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
bool swSurface;
|
|
||||||
}
|
|
||||||
sourceTransition;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
RenderCommand;
|
|
||||||
|
|
||||||
void renderQueue_init(void);
|
void renderQueue_init(void);
|
||||||
void renderQueue_free(void);
|
void renderQueue_free(void);
|
||||||
void renderQueue_clear(void);
|
void renderQueue_clear(void);
|
||||||
|
|||||||
@@ -406,8 +406,16 @@ static void testPayload(void)
|
|||||||
|
|
||||||
const uint64_t generation =
|
const uint64_t generation =
|
||||||
renderQueue_sourceBegin(RENDER_QUEUE_SOURCE_PRIMARY);
|
renderQueue_sourceBegin(RENDER_QUEUE_SOURCE_PRIMARY);
|
||||||
uint8_t bitmap[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
uint8_t bitmap[] =
|
||||||
const uint8_t bitmapExpected[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
{
|
||||||
|
1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
|
9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
|
};
|
||||||
|
const uint8_t bitmapExpected[] =
|
||||||
|
{
|
||||||
|
1, 2, 3, 4, 5, 6, 7, 8,
|
||||||
|
9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
|
};
|
||||||
uint8_t shape[] = { 11, 12, 13, 14, 15, 16, 17, 18 };
|
uint8_t shape[] = { 11, 12, 13, 14, 15, 16, 17, 18 };
|
||||||
const uint8_t shapeExpected[] = { 11, 12, 13, 14, 15, 16, 17, 18 };
|
const uint8_t shapeExpected[] = { 11, 12, 13, 14, 15, 16, 17, 18 };
|
||||||
LGColorTransform color =
|
LGColorTransform color =
|
||||||
@@ -419,7 +427,7 @@ static void testPayload(void)
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderQueue_sourceSwSurfaceDrawBitmap(RENDER_QUEUE_SOURCE_PRIMARY,
|
renderQueue_sourceSwSurfaceDrawBitmap(RENDER_QUEUE_SOURCE_PRIMARY,
|
||||||
generation, 5, 6, 2, 2, 4, bitmap, true);
|
generation, 5, 6, 2, 2, 8, bitmap, true);
|
||||||
renderQueue_sourceCursorImage(RENDER_QUEUE_SOURCE_PRIMARY, generation,
|
renderQueue_sourceCursorImage(RENDER_QUEUE_SOURCE_PRIMARY, generation,
|
||||||
LG_CURSOR_COLOR, 2, 2, 4, shape);
|
LG_CURSOR_COLOR, 2, 2, 4, shape);
|
||||||
renderQueue_sourceCursorColorTransform(RENDER_QUEUE_SOURCE_PRIMARY,
|
renderQueue_sourceCursorColorTransform(RENDER_QUEUE_SOURCE_PRIMARY,
|
||||||
@@ -442,7 +450,7 @@ static void testPayload(void)
|
|||||||
CHECK(f.bitmapY == 6);
|
CHECK(f.bitmapY == 6);
|
||||||
CHECK(f.bitmapWidth == 2);
|
CHECK(f.bitmapWidth == 2);
|
||||||
CHECK(f.bitmapHeight == 2);
|
CHECK(f.bitmapHeight == 2);
|
||||||
CHECK(f.bitmapStride == 4);
|
CHECK(f.bitmapStride == 8);
|
||||||
CHECK(f.bitmapTopDown);
|
CHECK(f.bitmapTopDown);
|
||||||
CHECK(f.bitmapSize == sizeof(bitmapExpected));
|
CHECK(f.bitmapSize == sizeof(bitmapExpected));
|
||||||
CHECK(memcmp(f.bitmap, bitmapExpected, sizeof(bitmapExpected)) == 0);
|
CHECK(memcmp(f.bitmap, bitmapExpected, sizeof(bitmapExpected)) == 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user