mirror of https://github.com/mgba-emu/mgba.git
OpenGL: Separate sizes of image and drawn layer for image
This commit is contained in:
parent
ce0b1507c3
commit
e3e8296105
|
@ -10,6 +10,11 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
struct Size {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
struct Rectangle {
|
||||
int x;
|
||||
int y;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -83,6 +83,7 @@ struct mGLES2Context {
|
|||
GLuint vbo;
|
||||
|
||||
struct Rectangle layerDims[VIDEO_LAYER_MAX];
|
||||
struct Size imageSizes[VIDEO_LAYER_MAX];
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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*);
|
||||
|
||||
|
|
Loading…
Reference in New Issue