OpenGL: Separate sizes of image and drawn layer for image

This commit is contained in:
Vicki Pfau 2023-03-19 02:23:37 -07:00
parent ce0b1507c3
commit e3e8296105
9 changed files with 164 additions and 42 deletions

View File

@ -10,6 +10,11 @@
CXX_GUARD_START
struct Size {
int width;
int height;
};
struct Rectangle {
int x;
int y;

View File

@ -33,6 +33,7 @@ static void mGLContextInit(struct VideoBackend* v, WHandle handle) {
UNUSED(handle);
struct mGLContext* context = (struct mGLContext*) v;
memset(context->layerDims, 0, sizeof(context->layerDims));
memset(context->imageSizes, -1, sizeof(context->imageSizes));
glGenTextures(2, context->tex);
glBindTexture(GL_TEXTURE_2D, context->tex[0]);
_initTex();
@ -48,17 +49,17 @@ static void mGLContextInit(struct VideoBackend* v, WHandle handle) {
}
}
static inline void _setTexDims(const struct Rectangle* dims) {
static inline void _setTexDims(int width, int height) {
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(dims->width), toPow2(dims->height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(dims->width), toPow2(dims->height), 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
#endif
#elif defined(__BIG_ENDIAN__)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(dims->width), toPow2(dims->height), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(dims->width), toPow2(dims->height), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, toPow2(width), toPow2(height), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
#endif
}
@ -75,14 +76,16 @@ static void mGLContextSetLayerDimensions(struct VideoBackend* v, enum VideoLayer
context->layerDims[layer].width = dims->width;
context->layerDims[layer].height = dims->height;
if (layer == VIDEO_LAYER_IMAGE) {
glBindTexture(GL_TEXTURE_2D, context->tex[0]);
_setTexDims(dims);
glBindTexture(GL_TEXTURE_2D, context->tex[1]);
_setTexDims(dims);
} else {
glBindTexture(GL_TEXTURE_2D, context->layers[layer]);
_setTexDims(dims);
if (context->imageSizes[layer].width <= 0 || context->imageSizes[layer].height <= 0) {
if (layer == VIDEO_LAYER_IMAGE) {
glBindTexture(GL_TEXTURE_2D, context->tex[0]);
_setTexDims(dims->width, dims->height);
glBindTexture(GL_TEXTURE_2D, context->tex[1]);
_setTexDims(dims->width, dims->height);
} else {
glBindTexture(GL_TEXTURE_2D, context->layers[layer]);
_setTexDims(dims->width, dims->height);
}
}
}
@ -195,6 +198,46 @@ void mGLContextDrawFrame(struct VideoBackend* v) {
glDisable(GL_BLEND);
}
static void mGLContextSetImageSize(struct VideoBackend* v, enum VideoLayer layer, int width, int height) {
struct mGLContext* context = (struct mGLContext*) v;
if (layer >= VIDEO_LAYER_MAX) {
return;
}
if (width <= 0 || height <= 0) {
context->imageSizes[layer].width = -1;
context->imageSizes[layer].height = -1;
width = context->layerDims[layer].width;
height = context->layerDims[layer].height;
} else {
context->imageSizes[layer].width = width;
context->imageSizes[layer].height = height;
}
if (layer == VIDEO_LAYER_IMAGE) {
glBindTexture(GL_TEXTURE_2D, context->tex[0]);
_setTexDims(width, height);
glBindTexture(GL_TEXTURE_2D, context->tex[1]);
_setTexDims(width, height);
} else {
glBindTexture(GL_TEXTURE_2D, context->layers[layer]);
_setTexDims(width, height);
}
}
static void mGLContextImageSize(struct VideoBackend* v, enum VideoLayer layer, int* width, int* height) {
struct mGLContext* context = (struct mGLContext*) v;
if (layer >= VIDEO_LAYER_MAX) {
return;
}
if (context->imageSizes[layer].width <= 0 || context->imageSizes[layer].height <= 0) {
*width = context->layerDims[layer].width;
*height = context->layerDims[layer].height;
} else {
*width = context->imageSizes[layer].width;
*height = context->imageSizes[layer].height;
}
}
void mGLContextPostFrame(struct VideoBackend* v, enum VideoLayer layer, const void* frame) {
struct mGLContext* context = (struct mGLContext*) v;
if (layer >= VIDEO_LAYER_MAX) {
@ -206,16 +249,24 @@ void mGLContextPostFrame(struct VideoBackend* v, enum VideoLayer layer, const vo
} else {
glBindTexture(GL_TEXTURE_2D, context->layers[layer]);
}
int width = context->imageSizes[layer].width;
int height = context->imageSizes[layer].height;
if (width <= 0 || height <= 0) {
width = context->layerDims[layer].width;
height = context->layerDims[layer].height;
}
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, context->layerDims[layer].width, context->layerDims[layer].height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
#else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, context->layerDims[layer].width, context->layerDims[layer].height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
#endif
#elif defined(__BIG_ENDIAN__)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, context->layerDims[layer].width, context->layerDims[layer].height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, frame);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, frame);
#else
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, context->layerDims[layer].width, context->layerDims[layer].height, GL_RGBA, GL_UNSIGNED_BYTE, frame);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frame);
#endif
}
@ -227,6 +278,8 @@ void mGLContextCreate(struct mGLContext* context) {
context->d.contextResized = mGLContextResized;
context->d.swap = NULL;
context->d.clear = mGLContextClear;
context->d.setImageSize = mGLContextSetImageSize;
context->d.imageSize = mGLContextImageSize;
context->d.setImage = mGLContextPostFrame;
context->d.drawFrame = mGLContextDrawFrame;
}

View File

@ -30,6 +30,7 @@ struct mGLContext {
GLuint tex[2];
GLuint layers[VIDEO_LAYER_MAX];
struct Rectangle layerDims[VIDEO_LAYER_MAX];
struct Size imageSizes[VIDEO_LAYER_MAX];
};
void mGLContextCreate(struct mGLContext*);

View File

@ -180,6 +180,20 @@ static void mGLES2ContextInit(struct VideoBackend* v, WHandle handle) {
context->finalShader.tex = 0;
}
static inline void _setTexDims(int width, int height) {
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
#endif
#elif defined(__BIG_ENDIAN__)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
#endif
}
static void mGLES2ContextSetLayerDimensions(struct VideoBackend* v, enum VideoLayer layer, const struct Rectangle* dims) {
struct mGLES2Context* context = (struct mGLES2Context*) v;
if (layer >= VIDEO_LAYER_MAX) {
@ -190,17 +204,9 @@ static void mGLES2ContextSetLayerDimensions(struct VideoBackend* v, enum VideoLa
context->layerDims[layer].height = dims->height;
glBindTexture(GL_TEXTURE_2D, context->tex[layer]);
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims->width, dims->height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims->width, dims->height, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0);
#endif
#elif defined(__BIG_ENDIAN__)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims->width, dims->height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dims->width, dims->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
#endif
if (context->imageSizes[layer].width <= 0 || context->imageSizes[layer].height <= 0) {
_setTexDims(dims->width, dims->height);
}
}
context->layerDims[layer].x = dims->x;
@ -455,22 +461,64 @@ void mGLES2ContextDrawFrame(struct VideoBackend* v) {
#endif
}
static void mGLES2ContextSetImageSize(struct VideoBackend* v, enum VideoLayer layer, int width, int height) {
struct mGLES2Context* context = (struct mGLES2Context*) v;
if (layer >= VIDEO_LAYER_MAX) {
return;
}
glBindTexture(GL_TEXTURE_2D, context->tex[layer]);
if (width <= 0 || height <= 0) {
context->imageSizes[layer].width = -1;
context->imageSizes[layer].height = -1;
width = context->layerDims[layer].width;
height = context->layerDims[layer].height;
} else {
context->imageSizes[layer].width = width;
context->imageSizes[layer].height = height;
}
_setTexDims(width, height);
}
static void mGLES2ContextImageSize(struct VideoBackend* v, enum VideoLayer layer, int* width, int* height) {
struct mGLES2Context* context = (struct mGLES2Context*) v;
if (layer >= VIDEO_LAYER_MAX) {
return;
}
if (context->imageSizes[layer].width <= 0 || context->imageSizes[layer].height <= 0) {
*width = context->layerDims[layer].width;
*height = context->layerDims[layer].height;
} else {
*width = context->imageSizes[layer].width;
*height = context->imageSizes[layer].height;
}
}
void mGLES2ContextPostFrame(struct VideoBackend* v, enum VideoLayer layer, const void* frame) {
struct mGLES2Context* context = (struct mGLES2Context*) v;
if (layer >= VIDEO_LAYER_MAX) {
return;
}
int width = context->imageSizes[layer].width;
int height = context->imageSizes[layer].height;
if (width <= 0 || height <= 0) {
width = context->layerDims[layer].width;
height = context->layerDims[layer].height;
}
glBindTexture(GL_TEXTURE_2D, context->tex[layer]);
#ifdef COLOR_16_BIT
#ifdef COLOR_5_6_5
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, context->layerDims[layer].width, context->layerDims[layer].height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, frame);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, context->layerDims[layer].width, context->layerDims[layer].height, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, frame);
#endif
#elif defined(__BIG_ENDIAN__)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, context->layerDims[layer].width, context->layerDims[layer].height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, frame);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, frame);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, context->layerDims[layer].width, context->layerDims[layer].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, frame);
#endif
}
@ -482,6 +530,8 @@ void mGLES2ContextCreate(struct mGLES2Context* context) {
context->d.contextResized = mGLES2ContextResized;
context->d.swap = NULL;
context->d.clear = mGLES2ContextClear;
context->d.setImageSize = mGLES2ContextSetImageSize;
context->d.imageSize = mGLES2ContextImageSize;
context->d.setImage = mGLES2ContextPostFrame;
context->d.drawFrame = mGLES2ContextDrawFrame;
context->shaders = 0;

View File

@ -83,6 +83,7 @@ struct mGLES2Context {
GLuint vbo;
struct Rectangle layerDims[VIDEO_LAYER_MAX];
struct Size imageSizes[VIDEO_LAYER_MAX];
unsigned width;
unsigned height;

View File

@ -271,6 +271,10 @@ QSize CoreController::screenDimensions() const {
return QSize(width, height);
}
unsigned CoreController::videoScale() const {
return m_threadContext.core->videoScale(m_threadContext.core);
}
void CoreController::loadConfig(ConfigController* config) {
Interrupter interrupter(this);
m_loadStateFlags = config->getOption("loadStateExtdata", m_loadStateFlags).toInt();

View File

@ -94,6 +94,7 @@ public:
mPlatform platform() const;
QSize screenDimensions() const;
unsigned videoScale() const;
bool supportsFeature(Feature feature) const { return m_threadContext.core->supportsFeature(m_threadContext.core, static_cast<mCoreFeature>(feature)); }
bool hardwareAccelerated() const { return m_hwaccel; }

View File

@ -648,13 +648,23 @@ void PainterGL::setMessagePainter(MessagePainter* messagePainter) {
}
void PainterGL::recenterLayers() {
if (!m_context) {
return;
}
const static std::initializer_list<VideoLayer> centeredLayers{VIDEO_LAYER_BACKGROUND, VIDEO_LAYER_IMAGE};
Rectangle frame = {0};
unsigned scale = std::max(1U, m_context->videoScale());
for (VideoLayer l : centeredLayers) {
Rectangle dims;
m_backend->layerDimensions(m_backend, l, &dims);
dims.x = 0;
dims.y = 0;
Rectangle dims{};
int width, height;
m_backend->imageSize(m_backend, l, &width, &height);
dims.width = width;
dims.height = height;
if (l != VIDEO_LAYER_IMAGE) {
dims.width *= scale;
dims.height *= scale;
m_backend->setLayerDimensions(m_backend, l, &dims);
}
RectangleUnion(&frame, &dims);
}
for (VideoLayer l : centeredLayers) {
@ -1035,12 +1045,7 @@ void PainterGL::setBackgroundImage(const QImage& image) {
makeCurrent();
}
Rectangle dims = {0, 0, 0, 0};
if (!image.isNull()) {
dims.width = static_cast<unsigned>(image.width());
dims.height = static_cast<unsigned>(image.height());
}
m_backend->setLayerDimensions(m_backend, VIDEO_LAYER_BACKGROUND, &dims);
m_backend->setImageSize(m_backend, VIDEO_LAYER_BACKGROUND, image.width(), image.height());
recenterLayers();
if (!image.isNull()) {

View File

@ -35,6 +35,8 @@ struct VideoBackend {
void (*swap)(struct VideoBackend*);
void (*clear)(struct VideoBackend*);
void (*contextResized)(struct VideoBackend*, unsigned w, unsigned h);
void (*setImageSize)(struct VideoBackend*, enum VideoLayer, int w, int h);
void (*imageSize)(struct VideoBackend*, enum VideoLayer, int* w, int* h);
void (*setImage)(struct VideoBackend*, enum VideoLayer, const void* frame);
void (*drawFrame)(struct VideoBackend*);