mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-20 14:22:00 +00:00
[client] egl: cache renderer GL state
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Some checks failed
build / client (Debug, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Debug, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:clang cxx:clang++], xdg-shell) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], libdecor) (push) Has been cancelled
build / client (Release, map[cc:gcc cxx:g++], xdg-shell) (push) Has been cancelled
build / module (push) Has been cancelled
build / host-linux (push) Has been cancelled
build / host-windows-cross (push) Has been cancelled
build / host-windows-native (push) Has been cancelled
build / idd (push) Has been cancelled
build / obs (clang) (push) Has been cancelled
build / obs (gcc) (push) Has been cancelled
build / docs (push) Has been cancelled
Track context-local GL bindings to avoid redundant program, framebuffer, buffer, texture, sampler, viewport, blend, and scissor state changes. Invalidate the cache across context switches, ImGui rendering, and shared object changes. Preserve CPU-backed texture upload correctness by explicitly clearing pixel unpack buffer bindings where required. This reduces hot-path driver overhead without adding waits or GPU synchronization.
This commit is contained in:
@@ -73,6 +73,7 @@ make_defines(
|
||||
add_library(renderer_EGL STATIC
|
||||
egl.c
|
||||
egldebug.c
|
||||
state.c
|
||||
shader.c
|
||||
texture_util.c
|
||||
texture.c
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "texture.h"
|
||||
#include "shader.h"
|
||||
#include "state.h"
|
||||
#include "model.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -386,7 +387,7 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
state.rect.x = max(0, state.rect.x - 1);
|
||||
state.rect.y = max(0, state.rect.y - 1);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
egl_stateBlend(true);
|
||||
switch(cursor->type)
|
||||
{
|
||||
case LG_CURSOR_MONOCHROME:
|
||||
@@ -394,14 +395,14 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
setCursorTexUniforms(cursor, &cursor->norm, true, pos.x, pos.y,
|
||||
size.w, size.h, scale);
|
||||
egl_shaderUse(cursor->norm.shader);
|
||||
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
||||
egl_stateBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
||||
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
||||
egl_modelRender(cursor->model);
|
||||
|
||||
setCursorTexUniforms(cursor, &cursor->mono, true, pos.x, pos.y,
|
||||
size.w, size.h, scale);
|
||||
egl_shaderUse(cursor->mono.shader);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
egl_stateBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
egl_modelSetTexture(cursor->model, cursor->mono.texture);
|
||||
egl_modelRender(cursor->model);
|
||||
break;
|
||||
@@ -412,14 +413,14 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
setCursorTexUniforms(cursor, &cursor->norm, false, pos.x, pos.y,
|
||||
size.w, size.h, scale);
|
||||
egl_shaderUse(cursor->norm.shader);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
egl_stateBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
||||
egl_modelRender(cursor->model);
|
||||
|
||||
setCursorTexUniforms(cursor, &cursor->mono, false, pos.x, pos.y,
|
||||
size.w, size.h, scale);
|
||||
egl_shaderUse(cursor->mono.shader);
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
egl_stateBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
|
||||
egl_modelSetTexture(cursor->model, cursor->mono.texture);
|
||||
egl_modelRender(cursor->model);
|
||||
break;
|
||||
@@ -430,13 +431,13 @@ struct CursorState egl_cursorRender(EGL_Cursor * cursor,
|
||||
setCursorTexUniforms(cursor, &cursor->norm, false, pos.x, pos.y,
|
||||
size.w, size.h, scale);
|
||||
egl_shaderUse(cursor->norm.shader);
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
egl_stateBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
egl_modelSetTexture(cursor->model, cursor->norm.texture);
|
||||
egl_modelRender(cursor->model);
|
||||
break;
|
||||
}
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
egl_stateBlend(false);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "app.h"
|
||||
#include "desktop_rects.h"
|
||||
#include "shader.h"
|
||||
#include "state.h"
|
||||
#include "cimgui.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -140,8 +141,8 @@ bool egl_damageRender(EGL_Damage * damage, LG_RendererRotate rotate, const struc
|
||||
update_matrix(damage);
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
egl_stateBlend(true);
|
||||
egl_stateBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
egl_uniformMatrix3x2fv(damage->uTransform, 1, GL_FALSE, damage->transform);
|
||||
egl_shaderUse(damage->shader);
|
||||
@@ -152,6 +153,6 @@ bool egl_damageRender(EGL_Damage * damage, LG_RendererRotate rotate, const struc
|
||||
|
||||
egl_desktopRectsRender(damage->mesh);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
egl_stateBlend(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "desktop.h"
|
||||
#include "state.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/option.h"
|
||||
#include "common/locking.h"
|
||||
@@ -476,10 +477,9 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
finalSizeY = height;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
egl_stateBindFramebuffer(0);
|
||||
egl_resetViewport(desktop->egl);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
|
||||
if (finalSizeX > width || finalSizeY > height)
|
||||
@@ -523,7 +523,6 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
egl_uniform1i (shader->uMapHDRPQ , desktop->hdrPQ);
|
||||
egl_shaderUse(shader->shader);
|
||||
egl_desktopRectsRender(desktop->mesh);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "desktop_rects.h"
|
||||
#include "state.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/KVMFR.h"
|
||||
#include "common/locking.h"
|
||||
@@ -54,14 +55,13 @@ bool egl_desktopRectsInit(EGL_DesktopRects ** rects_, int maxCount)
|
||||
memset(rects, 0, sizeof(*rects));
|
||||
|
||||
glGenVertexArrays(1, &rects->vao);
|
||||
glBindVertexArray(rects->vao);
|
||||
egl_stateBindVertexArray(rects->vao);
|
||||
|
||||
glGenBuffers(2, rects->buffers);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, rects->buffers[0]);
|
||||
egl_stateBindBuffer(GL_ARRAY_BUFFER, rects->buffers[0]);
|
||||
glBufferData(GL_ARRAY_BUFFER, maxCount * 8 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
GLushort indices[maxCount * 6];
|
||||
for (int i = 0; i < maxCount; ++i)
|
||||
@@ -77,8 +77,6 @@ bool egl_desktopRectsInit(EGL_DesktopRects ** rects_, int maxCount)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rects->buffers[1]);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof indices, indices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
rects->count = 0;
|
||||
rects->maxCount = maxCount;
|
||||
return true;
|
||||
@@ -92,6 +90,7 @@ void egl_desktopRectsFree(EGL_DesktopRects ** rects_)
|
||||
|
||||
glDeleteVertexArrays(1, &rects->vao);
|
||||
glDeleteBuffers(2, rects->buffers);
|
||||
egl_stateInvalidateShared();
|
||||
free(rects->lastVertices);
|
||||
free(rects);
|
||||
*rects_ = NULL;
|
||||
@@ -161,9 +160,8 @@ void egl_desktopRectsUpdate(EGL_DesktopRects * rects, const struct DamageRects *
|
||||
rects->lastVerticesCount = count;
|
||||
memcpy(rects->lastVertices, vertices, sizeof(GLfloat) * count);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, rects->buffers[0]);
|
||||
egl_stateBindBuffer(GL_ARRAY_BUFFER, rects->buffers[0]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, rects->count * 8 * sizeof(GLfloat), vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
static void desktopToGLSpace(double matrix[6], int width, int height, double translateX,
|
||||
@@ -299,7 +297,6 @@ void egl_desktopRectsRender(EGL_DesktopRects * rects)
|
||||
if (unlikely(!rects->count))
|
||||
return;
|
||||
|
||||
glBindVertexArray(rects->vao);
|
||||
egl_stateBindVertexArray(rects->vao);
|
||||
glDrawElements(GL_TRIANGLES, 6 * rects->count, GL_UNSIGNED_SHORT, NULL);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "filter.h"
|
||||
#include "framebuffer.h"
|
||||
#include "state.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
@@ -74,16 +75,21 @@ void egl_effectFree(EGL_Effect ** effect)
|
||||
if (!*effect)
|
||||
return;
|
||||
|
||||
bool deletedSampler = false;
|
||||
EGL_EffectPass * pass = (*effect)->passes;
|
||||
while(pass)
|
||||
{
|
||||
EGL_EffectPass * next = pass->next;
|
||||
glDeleteSamplers(1, &pass->sampler);
|
||||
deletedSampler = true;
|
||||
egl_framebufferFree(&pass->framebuffer);
|
||||
free(pass);
|
||||
pass = next;
|
||||
}
|
||||
|
||||
if (deletedSampler)
|
||||
egl_stateInvalidateShared();
|
||||
|
||||
free(*effect);
|
||||
*effect = NULL;
|
||||
}
|
||||
@@ -215,9 +221,7 @@ EGL_Texture * egl_effectRun(EGL_Effect * effect, EGL_FilterRects * rects,
|
||||
|
||||
egl_framebufferBind(pass->framebuffer);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
egl_textureBind(texture);
|
||||
glBindSampler(0, pass->sampler);
|
||||
egl_textureBindWithSampler(texture, pass->sampler);
|
||||
|
||||
egl_uniformMatrix3x2fv(pass->uTransform, 1, GL_FALSE, rects->matrix);
|
||||
egl_uniform2f(pass->uDesktopSize, rects->width, rects->height);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "egl_dynprocs.h"
|
||||
#include "model.h"
|
||||
#include "shader.h"
|
||||
#include "state.h"
|
||||
#include "damage.h"
|
||||
#include "desktop.h"
|
||||
#include "cursor.h"
|
||||
@@ -298,7 +299,10 @@ static void egl_deinitialize(LG_Renderer * renderer)
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
|
||||
if (this->imgui)
|
||||
{
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
egl_stateInvalidate();
|
||||
}
|
||||
|
||||
ringbuffer_free(&this->importTimings);
|
||||
|
||||
@@ -483,13 +487,14 @@ static void egl_update_scale_type(struct Inst * this)
|
||||
|
||||
void egl_resetViewport(EGL * this)
|
||||
{
|
||||
glViewport(0, 0, this->width, this->height);
|
||||
egl_stateViewport(0, 0, this->width, this->height);
|
||||
}
|
||||
|
||||
static void egl_onResize(LG_Renderer * renderer, const int width, const int height, const double scale,
|
||||
const LG_RendererRect destRect, LG_RendererRotate rotate)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
|
||||
this->width = width * scale;
|
||||
this->height = height * scale;
|
||||
@@ -501,7 +506,7 @@ static void egl_onResize(LG_Renderer * renderer, const int width, const int heig
|
||||
this->destRect.w = destRect.w * scale;
|
||||
this->destRect.h = destRect.h * scale;
|
||||
|
||||
glViewport(0, 0, this->width, this->height);
|
||||
egl_stateViewport(0, 0, this->width, this->height);
|
||||
|
||||
if (destRect.valid)
|
||||
{
|
||||
@@ -540,6 +545,7 @@ static void egl_onResize(LG_Renderer * renderer, const int width, const int heig
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplOpenGL3_Init("#version 300 es");
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
egl_stateInvalidate();
|
||||
|
||||
egl_damageResize(this->damage, this->translateX, this->translateY, this->scaleX, this->scaleY);
|
||||
egl_desktopResize(this->desktop, this->width, this->height);
|
||||
@@ -602,8 +608,12 @@ static bool egl_onFrameFormat(LG_Renderer * renderer, const LG_RendererFormat fo
|
||||
DEBUG_ERROR("Failed to make the frame context current");
|
||||
return false;
|
||||
}
|
||||
|
||||
egl_stateInvalidate();
|
||||
}
|
||||
|
||||
egl_stateCheckShared();
|
||||
|
||||
if (likely(this->scalePointer))
|
||||
{
|
||||
float scale = max(1.0f, (float)format.screenWidth / this->width);
|
||||
@@ -649,6 +659,7 @@ static bool egl_onFrame(LG_Renderer * renderer, const FrameBuffer * frame, int d
|
||||
const FrameDamageRect * damageRects, int damageRectsCount)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
|
||||
uint64_t start = nanotime();
|
||||
if (unlikely(!egl_desktopUpdate(
|
||||
@@ -922,6 +933,7 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
}
|
||||
|
||||
eglMakeCurrent(this->display, this->surface, this->surface, this->context);
|
||||
egl_stateInvalidate();
|
||||
const char * gl_exts = (const char *)glGetString(GL_EXTENSIONS);
|
||||
if (!gl_exts)
|
||||
{
|
||||
@@ -1038,6 +1050,7 @@ static bool egl_renderStartup(LG_Renderer * renderer, bool useDMA)
|
||||
DEBUG_ERROR("Failed to initialize ImGui");
|
||||
return false;
|
||||
}
|
||||
egl_stateInvalidate();
|
||||
|
||||
app_overlayConfigRegister("EGL", egl_configUI, this);
|
||||
|
||||
@@ -1067,7 +1080,7 @@ inline static void renderLetterBox(struct Inst * this)
|
||||
if (hLB || vLB)
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
egl_stateScissor(true);
|
||||
|
||||
if (hLB)
|
||||
{
|
||||
@@ -1094,7 +1107,7 @@ inline static void renderLetterBox(struct Inst * this)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
egl_stateScissor(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1103,6 +1116,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
void (*preSwap)(void * udata), void * udata)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
EGLint bufferAge = egl_bufferAge(this);
|
||||
bool renderAll = invalidateWindow || this->hadOverlay ||
|
||||
bufferAge <= 0 || bufferAge > MAX_BUFFER_AGE ||
|
||||
@@ -1213,6 +1227,7 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
|
||||
egl_stateInvalidate();
|
||||
|
||||
for (int i = 0; i < damageIdx; ++i)
|
||||
damage[i].y = this->height - damage[i].y - damage[i].h;
|
||||
@@ -1268,9 +1283,12 @@ static bool egl_render(LG_Renderer * renderer, LG_RendererRotate rotate,
|
||||
static void * egl_createTexture(LG_Renderer * renderer,
|
||||
int width, int height, uint8_t * data)
|
||||
{
|
||||
egl_stateCheckShared();
|
||||
|
||||
GLuint tex;
|
||||
glGenTextures(1, &tex);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, tex);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
@@ -1289,8 +1307,6 @@ static void * egl_createTexture(LG_Renderer * renderer,
|
||||
GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return (void*)(intptr_t)tex;
|
||||
}
|
||||
|
||||
@@ -1298,11 +1314,13 @@ static void egl_freeTexture(LG_Renderer * renderer, void * texture)
|
||||
{
|
||||
GLuint tex = (GLuint)(intptr_t)texture;
|
||||
glDeleteTextures(1, &tex);
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
|
||||
static void egl_spiceConfigure(LG_Renderer * renderer, int width, int height)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
this->spiceWidth = width;
|
||||
this->spiceHeight = height;
|
||||
egl_desktopSpiceConfigure(this->desktop, width, height);
|
||||
@@ -1312,6 +1330,7 @@ static void egl_spiceDrawFill(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, uint32_t color)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
egl_desktopSpiceDrawFill(this->desktop, x, y, width, height, color);
|
||||
}
|
||||
|
||||
@@ -1319,6 +1338,7 @@ static void egl_spiceDrawBitmap(LG_Renderer * renderer, int x, int y, int width,
|
||||
int height, int stride, uint8_t * data, bool topDown)
|
||||
{
|
||||
struct Inst * this = UPCAST(struct Inst, renderer);
|
||||
egl_stateCheckShared();
|
||||
egl_desktopSpiceDrawBitmap(this->desktop, x, y, width, height, stride,
|
||||
data, topDown);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "state.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -62,6 +63,7 @@ void egl_framebufferFree(EGL_Framebuffer ** fb)
|
||||
|
||||
egl_textureFree(&this->tex);
|
||||
glDeleteFramebuffers(1, &this->fbo);
|
||||
egl_stateInvalidate();
|
||||
free(this);
|
||||
*fb = NULL;
|
||||
}
|
||||
@@ -78,11 +80,11 @@ bool egl_framebufferSetup(EGL_Framebuffer * this, enum EGL_PixelFormat pixFmt,
|
||||
GLuint tex;
|
||||
egl_textureGet(this->tex, &tex, NULL, NULL, NULL);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, tex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, this->fbo);
|
||||
egl_stateBindFramebuffer(this->fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, tex, 0);
|
||||
glDrawBuffers(1, &(GLenum){GL_COLOR_ATTACHMENT0});
|
||||
@@ -90,19 +92,20 @@ bool egl_framebufferSetup(EGL_Framebuffer * this, enum EGL_PixelFormat pixFmt,
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
egl_stateBindFramebuffer(0);
|
||||
DEBUG_ERROR("Failed to setup the framebuffer: 0x%x", status);
|
||||
return false;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
egl_stateBindFramebuffer(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void egl_framebufferBind(EGL_Framebuffer * this)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, this->fbo);
|
||||
glViewport(0, 0, this->tex->format.width, this->tex->format.height);
|
||||
egl_stateBindFramebuffer(this->fbo);
|
||||
egl_stateViewport(0, 0,
|
||||
this->tex->format.width, this->tex->format.height);
|
||||
}
|
||||
|
||||
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "model.h"
|
||||
#include "shader.h"
|
||||
#include "state.h"
|
||||
#include "texture.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
@@ -88,6 +89,8 @@ void egl_modelFree(EGL_Model ** model)
|
||||
if ((*model)->vao)
|
||||
glDeleteVertexArrays(1, &(*model)->vao);
|
||||
|
||||
egl_stateInvalidateShared();
|
||||
|
||||
free(*model);
|
||||
*model = NULL;
|
||||
}
|
||||
@@ -169,16 +172,19 @@ void egl_modelRender(EGL_Model * model)
|
||||
if (model->rebuild)
|
||||
{
|
||||
if (model->buffer)
|
||||
{
|
||||
glDeleteBuffers(1, &model->buffer);
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
|
||||
if (!model->vao)
|
||||
glGenVertexArrays(1, &model->vao);
|
||||
|
||||
glBindVertexArray(model->vao);
|
||||
egl_stateBindVertexArray(model->vao);
|
||||
|
||||
/* create a buffer large enough */
|
||||
glGenBuffers(1, &model->buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, model->buffer);
|
||||
egl_stateBindBuffer(GL_ARRAY_BUFFER, model->buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (model->vertexCount * 5), NULL, GL_STATIC_DRAW);
|
||||
|
||||
GLintptr offset = 0;
|
||||
@@ -206,12 +212,10 @@ void egl_modelRender(EGL_Model * model)
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(GLfloat) * model->vertexCount * 3));
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
model->rebuild = false;
|
||||
}
|
||||
|
||||
glBindVertexArray(model->vao);
|
||||
egl_stateBindVertexArray(model->vao);
|
||||
|
||||
if (model->shader)
|
||||
egl_shaderUse(model->shader);
|
||||
@@ -230,10 +234,6 @@ void egl_modelRender(EGL_Model * model)
|
||||
}
|
||||
ll_unlock(model->verticies);
|
||||
|
||||
/* unbind and cleanup */
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
void egl_modelSetShader(EGL_Model * model, EGL_Shader * shader)
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "shader.h"
|
||||
#include "state.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/stringutils.h"
|
||||
#include "util.h"
|
||||
@@ -78,7 +79,10 @@ void egl_shaderFree(EGL_Shader ** shader)
|
||||
return;
|
||||
|
||||
if (this->hasShader)
|
||||
{
|
||||
glDeleteProgram(this->shader);
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
|
||||
EGL_Uniform * uniform = this->uniforms;
|
||||
while (uniform)
|
||||
@@ -161,6 +165,7 @@ static bool shaderCompile(EGL_Shader * this, const char * vertex_code,
|
||||
if (this->hasShader)
|
||||
{
|
||||
glDeleteProgram(this->shader);
|
||||
egl_stateInvalidateShared();
|
||||
this->hasShader = false;
|
||||
}
|
||||
|
||||
@@ -714,7 +719,7 @@ void egl_shaderUse(EGL_Shader * this)
|
||||
return;
|
||||
}
|
||||
|
||||
glUseProgram(this->shader);
|
||||
egl_stateUseProgram(this->shader);
|
||||
|
||||
while(this->dirtyUniforms)
|
||||
{
|
||||
|
||||
55
client/renderers/EGL/state.c
Normal file
55
client/renderers/EGL/state.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "state.h"
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include <string.h>
|
||||
|
||||
_Thread_local EGL_StateCache g_eglState;
|
||||
static _Thread_local unsigned int localGeneration;
|
||||
static atomic_uint sharedGeneration = 1;
|
||||
|
||||
static void stateInvalidate(unsigned int generation)
|
||||
{
|
||||
memset(&g_eglState, 0, sizeof(g_eglState));
|
||||
localGeneration = generation;
|
||||
}
|
||||
|
||||
void egl_stateInvalidate(void)
|
||||
{
|
||||
stateInvalidate(atomic_load_explicit(
|
||||
&sharedGeneration, memory_order_relaxed));
|
||||
}
|
||||
|
||||
void egl_stateInvalidateShared(void)
|
||||
{
|
||||
const unsigned int generation = atomic_fetch_add_explicit(
|
||||
&sharedGeneration, 1, memory_order_release) + 1;
|
||||
stateInvalidate(generation);
|
||||
}
|
||||
|
||||
void egl_stateCheckShared(void)
|
||||
{
|
||||
const unsigned int generation = atomic_load_explicit(
|
||||
&sharedGeneration, memory_order_acquire);
|
||||
if (localGeneration != generation)
|
||||
stateInvalidate(generation);
|
||||
}
|
||||
266
client/renderers/EGL/state.h
Normal file
266
client/renderers/EGL/state.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2026 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <GLES3/gl3.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
#define EGL_STATE_TEXTURE_UNITS 16
|
||||
|
||||
/*
|
||||
* GL bindings are context-local and the renderer keeps each context on its
|
||||
* own thread, so the cache is thread-local too. Code that changes tracked GL
|
||||
* state without these helpers must invalidate the cache afterwards.
|
||||
*/
|
||||
|
||||
typedef struct EGL_StateBinding
|
||||
{
|
||||
GLuint value;
|
||||
bool valid;
|
||||
}
|
||||
EGL_StateBinding;
|
||||
|
||||
typedef struct EGL_StateTextureUnit
|
||||
{
|
||||
EGL_StateBinding texture2D;
|
||||
EGL_StateBinding textureExternal;
|
||||
EGL_StateBinding sampler;
|
||||
}
|
||||
EGL_StateTextureUnit;
|
||||
|
||||
typedef struct EGL_StateCache
|
||||
{
|
||||
EGL_StateBinding program;
|
||||
EGL_StateBinding framebuffer;
|
||||
EGL_StateBinding vertexArray;
|
||||
EGL_StateBinding arrayBuffer;
|
||||
EGL_StateBinding pixelUnpackBuffer;
|
||||
EGL_StateBinding activeTexture;
|
||||
EGL_StateTextureUnit textureUnit[EGL_STATE_TEXTURE_UNITS];
|
||||
|
||||
bool viewportValid;
|
||||
GLint viewportX;
|
||||
GLint viewportY;
|
||||
GLsizei viewportWidth;
|
||||
GLsizei viewportHeight;
|
||||
|
||||
bool blendValid;
|
||||
bool blend;
|
||||
bool blendFuncValid;
|
||||
GLenum blendSrc;
|
||||
GLenum blendDst;
|
||||
|
||||
bool scissorValid;
|
||||
bool scissor;
|
||||
}
|
||||
EGL_StateCache;
|
||||
|
||||
extern _Thread_local EGL_StateCache g_eglState;
|
||||
|
||||
/* Invalidates only the current context/thread cache. */
|
||||
void egl_stateInvalidate(void);
|
||||
|
||||
/* Invalidates all context caches at their next synchronization point. */
|
||||
void egl_stateInvalidateShared(void);
|
||||
void egl_stateCheckShared(void);
|
||||
|
||||
static inline void egl_stateUseProgram(GLuint program)
|
||||
{
|
||||
if (g_eglState.program.valid && g_eglState.program.value == program)
|
||||
return;
|
||||
|
||||
glUseProgram(program);
|
||||
g_eglState.program.value = program;
|
||||
g_eglState.program.valid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateBindFramebuffer(GLuint framebuffer)
|
||||
{
|
||||
if (g_eglState.framebuffer.valid &&
|
||||
g_eglState.framebuffer.value == framebuffer)
|
||||
return;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||
g_eglState.framebuffer.value = framebuffer;
|
||||
g_eglState.framebuffer.valid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateBindVertexArray(GLuint vertexArray)
|
||||
{
|
||||
if (g_eglState.vertexArray.valid &&
|
||||
g_eglState.vertexArray.value == vertexArray)
|
||||
return;
|
||||
|
||||
glBindVertexArray(vertexArray);
|
||||
g_eglState.vertexArray.value = vertexArray;
|
||||
g_eglState.vertexArray.valid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateBindBuffer(GLenum target, GLuint buffer)
|
||||
{
|
||||
EGL_StateBinding * binding;
|
||||
switch(target)
|
||||
{
|
||||
case GL_ARRAY_BUFFER:
|
||||
binding = &g_eglState.arrayBuffer;
|
||||
break;
|
||||
|
||||
case GL_PIXEL_UNPACK_BUFFER:
|
||||
binding = &g_eglState.pixelUnpackBuffer;
|
||||
break;
|
||||
|
||||
/* GL_ELEMENT_ARRAY_BUFFER belongs to the currently bound VAO. */
|
||||
default:
|
||||
glBindBuffer(target, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (binding->valid && binding->value == buffer)
|
||||
return;
|
||||
|
||||
glBindBuffer(target, buffer);
|
||||
binding->value = buffer;
|
||||
binding->valid = true;
|
||||
}
|
||||
|
||||
static inline bool egl_stateActiveTextureUnit(GLuint unit)
|
||||
{
|
||||
const GLenum texture = GL_TEXTURE0 + unit;
|
||||
if (!g_eglState.activeTexture.valid ||
|
||||
g_eglState.activeTexture.value != texture)
|
||||
{
|
||||
glActiveTexture(texture);
|
||||
g_eglState.activeTexture.value = texture;
|
||||
g_eglState.activeTexture.valid = true;
|
||||
}
|
||||
|
||||
return unit < EGL_STATE_TEXTURE_UNITS;
|
||||
}
|
||||
|
||||
static inline void egl_stateBindTexture(GLuint unit, GLenum target,
|
||||
GLuint texture)
|
||||
{
|
||||
if (!egl_stateActiveTextureUnit(unit))
|
||||
{
|
||||
glBindTexture(target, texture);
|
||||
return;
|
||||
}
|
||||
|
||||
EGL_StateBinding * binding;
|
||||
switch(target)
|
||||
{
|
||||
case GL_TEXTURE_2D:
|
||||
binding = &g_eglState.textureUnit[unit].texture2D;
|
||||
break;
|
||||
|
||||
case GL_TEXTURE_EXTERNAL_OES:
|
||||
binding = &g_eglState.textureUnit[unit].textureExternal;
|
||||
break;
|
||||
|
||||
default:
|
||||
glBindTexture(target, texture);
|
||||
return;
|
||||
}
|
||||
|
||||
if (binding->valid && binding->value == texture)
|
||||
return;
|
||||
|
||||
glBindTexture(target, texture);
|
||||
binding->value = texture;
|
||||
binding->valid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateBindSampler(GLuint unit, GLuint sampler)
|
||||
{
|
||||
if (unit >= EGL_STATE_TEXTURE_UNITS)
|
||||
{
|
||||
glBindSampler(unit, sampler);
|
||||
return;
|
||||
}
|
||||
|
||||
EGL_StateBinding * binding = &g_eglState.textureUnit[unit].sampler;
|
||||
if (binding->valid && binding->value == sampler)
|
||||
return;
|
||||
|
||||
glBindSampler(unit, sampler);
|
||||
binding->value = sampler;
|
||||
binding->valid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateViewport(GLint x, GLint y, GLsizei width,
|
||||
GLsizei height)
|
||||
{
|
||||
if (g_eglState.viewportValid &&
|
||||
g_eglState.viewportX == x &&
|
||||
g_eglState.viewportY == y &&
|
||||
g_eglState.viewportWidth == width &&
|
||||
g_eglState.viewportHeight == height)
|
||||
return;
|
||||
|
||||
glViewport(x, y, width, height);
|
||||
g_eglState.viewportX = x;
|
||||
g_eglState.viewportY = y;
|
||||
g_eglState.viewportWidth = width;
|
||||
g_eglState.viewportHeight = height;
|
||||
g_eglState.viewportValid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateBlend(bool enabled)
|
||||
{
|
||||
if (g_eglState.blendValid && g_eglState.blend == enabled)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
glEnable(GL_BLEND);
|
||||
else
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
g_eglState.blend = enabled;
|
||||
g_eglState.blendValid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateBlendFunc(GLenum src, GLenum dst)
|
||||
{
|
||||
if (g_eglState.blendFuncValid &&
|
||||
g_eglState.blendSrc == src && g_eglState.blendDst == dst)
|
||||
return;
|
||||
|
||||
glBlendFunc(src, dst);
|
||||
g_eglState.blendSrc = src;
|
||||
g_eglState.blendDst = dst;
|
||||
g_eglState.blendFuncValid = true;
|
||||
}
|
||||
|
||||
static inline void egl_stateScissor(bool enabled)
|
||||
{
|
||||
if (g_eglState.scissorValid && g_eglState.scissor == enabled)
|
||||
return;
|
||||
|
||||
if (enabled)
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
else
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
g_eglState.scissor = enabled;
|
||||
g_eglState.scissorValid = true;
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "texture.h"
|
||||
#include "state.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
@@ -88,6 +89,7 @@ void egl_textureFree(EGL_Texture ** tex)
|
||||
return;
|
||||
|
||||
glDeleteSamplers(1, &this->sampler);
|
||||
egl_stateInvalidateShared();
|
||||
|
||||
this->ops.free(this);
|
||||
*tex = NULL;
|
||||
@@ -207,7 +209,12 @@ enum EGL_TexStatus egl_textureProcess(EGL_Texture * this)
|
||||
|
||||
enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindSampler(0, this->sampler);
|
||||
return egl_textureBindWithSampler(this, this->sampler);
|
||||
}
|
||||
|
||||
enum EGL_TexStatus egl_textureBindWithSampler(EGL_Texture * this,
|
||||
GLuint sampler)
|
||||
{
|
||||
egl_stateBindSampler(0, sampler);
|
||||
return this->ops.bind(this);
|
||||
}
|
||||
|
||||
@@ -145,6 +145,8 @@ static inline EGL_TexStatus egl_textureGet(EGL_Texture * texture, GLuint * tex,
|
||||
}
|
||||
|
||||
enum EGL_TexStatus egl_textureBind(EGL_Texture * texture);
|
||||
enum EGL_TexStatus egl_textureBindWithSampler(EGL_Texture * texture,
|
||||
GLuint sampler);
|
||||
|
||||
typedef void * PostProcessHandle;
|
||||
PostProcessHandle egl_textureAddFilter(EGL_Texture * texture,
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "texture_buffer.h"
|
||||
#include "state.h"
|
||||
|
||||
#include "egldebug.h"
|
||||
|
||||
@@ -35,7 +36,10 @@ static void egl_texBuffer_cleanup(TextureBuffer * this)
|
||||
egl_texUtilFreeBuffers(this->buf, this->texCount);
|
||||
|
||||
if (this->tex[0])
|
||||
{
|
||||
glDeleteTextures(this->texCount, this->tex);
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
|
||||
for (int i = 0; i < EGL_TEX_BUFFER_MAX; ++i)
|
||||
{
|
||||
@@ -89,9 +93,10 @@ bool egl_texBufferSetup(EGL_Texture * texture, const EGL_TexSetup * setup)
|
||||
egl_texBuffer_cleanup(this);
|
||||
|
||||
glGenTextures(this->texCount, this->tex);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
for(int i = 0; i < this->texCount; ++i)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, this->tex[i]);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, this->tex[i]);
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
texture->format.intFormat,
|
||||
@@ -103,7 +108,6 @@ bool egl_texBufferSetup(EGL_Texture * texture, const EGL_TexSetup * setup)
|
||||
NULL);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
this->bufIndex = 0;
|
||||
this->rIndex = -1;
|
||||
|
||||
@@ -118,7 +122,8 @@ static bool egl_texBufferUpdate(EGL_Texture * texture, const EGL_TexUpdate * upd
|
||||
TextureBuffer * this = UPCAST(TextureBuffer, texture);
|
||||
DEBUG_ASSERT(update->type == EGL_TEXTYPE_BUFFER);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, this->tex[0]);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, this->tex[0]);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, update->stride);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0,
|
||||
@@ -129,8 +134,6 @@ static bool egl_texBufferUpdate(EGL_Texture * texture, const EGL_TexUpdate * upd
|
||||
texture->format.format,
|
||||
texture->format.dataType,
|
||||
update->buffer);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -292,8 +295,8 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture)
|
||||
if (!keepLocked)
|
||||
LG_UNLOCK(this->copyLock);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, tex);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, texture->format.stride);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
@@ -303,9 +306,6 @@ EGL_TexStatus egl_texBufferStreamProcess(EGL_Texture * texture)
|
||||
texture->format.format,
|
||||
texture->format.dataType,
|
||||
(const void *)0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
this->sync[index] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
if (unlikely(!this->sync[index]))
|
||||
{
|
||||
@@ -348,7 +348,7 @@ EGL_TexStatus egl_texBufferBind(EGL_Texture * texture)
|
||||
if ((status = texture->ops.get(texture, &tex, NULL)) != EGL_TEX_STATUS_OK)
|
||||
return status;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_2D, tex);
|
||||
return EGL_TEX_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "texture.h"
|
||||
#include "texture_buffer.h"
|
||||
#include "state.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "common/array.h"
|
||||
@@ -82,7 +83,10 @@ static void egl_texDMABUFCleanup(EGL_Texture * texture)
|
||||
egl_texUtilFreeBuffers(parent->buf, parent->texCount);
|
||||
|
||||
if (parent->tex[0])
|
||||
{
|
||||
glDeleteTextures(parent->texCount, parent->tex);
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
}
|
||||
|
||||
// dmabuf functions
|
||||
@@ -245,7 +249,7 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
|
||||
fdImage->texIndex = slot;
|
||||
INTERLOCKED_SECTION(parent->copyLock,
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[slot]);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_EXTERNAL_OES, parent->tex[slot]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
@@ -332,7 +336,7 @@ static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture)
|
||||
if ((status = egl_texDMABUFGet(texture, &tex, NULL)) != EGL_TEX_STATUS_OK)
|
||||
return status;
|
||||
|
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
|
||||
egl_stateBindTexture(0, GL_TEXTURE_EXTERNAL_OES, tex);
|
||||
return EGL_TEX_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "texture.h"
|
||||
#include "state.h"
|
||||
#include "texture_util.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
@@ -112,7 +113,7 @@ bool egl_texUtilGenBuffers(const EGL_TexFormat * fmt, EGL_TexBuffer * buffers,
|
||||
|
||||
buffer->size = fmt->dataSize;
|
||||
glGenBuffers(1, &buffer->pbo);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
g_egl_dynProcs.glBufferStorageEXT(
|
||||
GL_PIXEL_UNPACK_BUFFER,
|
||||
fmt->dataSize,
|
||||
@@ -131,6 +132,7 @@ bool egl_texUtilGenBuffers(const EGL_TexFormat * fmt, EGL_TexBuffer * buffers,
|
||||
|
||||
void egl_texUtilFreeBuffers(EGL_TexBuffer * buffers, int count)
|
||||
{
|
||||
bool deleted = false;
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
EGL_TexBuffer *buffer = &buffers[i];
|
||||
@@ -140,13 +142,17 @@ void egl_texUtilFreeBuffers(EGL_TexBuffer * buffers, int count)
|
||||
|
||||
egl_texUtilUnmapBuffer(buffer);
|
||||
glDeleteBuffers(1, &buffer->pbo);
|
||||
deleted = true;
|
||||
buffer->pbo = 0;
|
||||
}
|
||||
|
||||
if (deleted)
|
||||
egl_stateInvalidateShared();
|
||||
}
|
||||
|
||||
bool egl_texUtilMapBuffer(EGL_TexBuffer * buffer)
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
buffer->map = glMapBufferRange(
|
||||
GL_PIXEL_UNPACK_BUFFER,
|
||||
0,
|
||||
@@ -160,7 +166,7 @@ bool egl_texUtilMapBuffer(EGL_TexBuffer * buffer)
|
||||
if (!buffer->map)
|
||||
DEBUG_GL_ERROR("glMapBufferRange failed of %lu bytes", buffer->size);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
return buffer->map;
|
||||
}
|
||||
|
||||
@@ -169,8 +175,8 @@ void egl_texUtilUnmapBuffer(EGL_TexBuffer * buffer)
|
||||
if (!buffer->map)
|
||||
return;
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer->pbo);
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
egl_stateBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
buffer->map = NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user