@@ -1172,97 +1172,97 @@ void OpenGLBackend::ReleaseAnimBuffer(co
#ifndef NO_GL_BUFFER_SYNC
if (this->persistent_mapping_supported) {
_glDeleteSync(this->sync_anim_mapping);
this->sync_anim_mapping = nullptr;
}
#endif
/* Update changed rect of the video buffer texture. */
if (update_rect.left != update_rect.right) {
_glActiveTexture(GL_TEXTURE0);
_glBindTexture(GL_TEXTURE_2D, this->anim_texture);
_glPixelStorei(GL_UNPACK_ROW_LENGTH, _screen.pitch);
_glTexSubImage2D(GL_TEXTURE_2D, 0, update_rect.left, update_rect.top, update_rect.right - update_rect.left, update_rect.bottom - update_rect.top, GL_RED, GL_UNSIGNED_BYTE, (GLvoid *)(size_t)(update_rect.top * _screen.pitch + update_rect.left));
if (this->persistent_mapping_supported) this->sync_anim_mapping = _glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
/* virtual */ Sprite *OpenGLBackend::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator)
{
/* Allocate and construct sprite data. */
Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sizeof(OpenGLSprite));
OpenGLSprite *gl_sprite = (OpenGLSprite *)dest_sprite->data;
new (gl_sprite) OpenGLSprite(sprite->width, sprite->height, sprite->type == ST_FONT ? 1 : ZOOM_LVL_COUNT, sprite->colours);
/* Upload texture data. */
for (int i = 0; i < (sprite->type == ST_FONT ? 1 : ZOOM_LVL_COUNT); i++) {
gl_sprite->Update(sprite[i].width, sprite[i].height, i, sprite[i].data);
dest_sprite->height = sprite->height;
dest_sprite->width = sprite->width;
dest_sprite->x_offs = sprite->x_offs;
dest_sprite->y_offs = sprite->y_offs;
return dest_sprite;
/**
* Render a sprite to the back buffer.
* @param gl_sprite Sprite to render.
* @param x X position of the sprite.
* @param y Y position of the sprite.
* @param zoom Zoom level to use.
*/
void OpenGLBackend::RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, uint x, uint y, ZoomLevel zoom)
void OpenGLBackend::RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, int x, int y, ZoomLevel zoom)
/* Set textures. */
bool rgb = gl_sprite->BindTextures();
_glActiveTexture(GL_TEXTURE0 + 1);
_glBindTexture(GL_TEXTURE_1D, this->pal_texture);
/* Set palette remap. */
_glActiveTexture(GL_TEXTURE0 + 3);
if (pal != PAL_NONE) {
_glBindTexture(GL_TEXTURE_1D, OpenGLSprite::pal_tex);
if (pal != this->last_sprite_pal) {
/* Different remap palette in use, update texture. */
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER, OpenGLSprite::pal_pbo);
_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
_glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, 256, GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1);
_glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 256, GL_RED, GL_UNSIGNED_BYTE, 0);
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
this->last_sprite_pal = pal;
} else {
_glBindTexture(GL_TEXTURE_1D, OpenGLSprite::pal_identity);
/* Set up shader program. */
Dimension dim = gl_sprite->GetSize(zoom);
_glUseProgram(this->sprite_program);
_glUniform4f(this->sprite_sprite_loc, (float)x, (float)y, (float)dim.width, (float)dim.height);
_glUniform1f(this->sprite_zoom_loc, (float)(zoom - ZOOM_LVL_BEGIN));
_glUniform2f(this->sprite_screen_loc, (float)_screen.width, (float)_screen.height);
_glUniform1i(this->sprite_rgb_loc, rgb ? 1 : 0);
_glUniform1i(this->sprite_crash_loc, pal == PALETTE_CRASH ? 1 : 0);
_glBindVertexArray(this->vao_quad);
_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* static */ GLuint OpenGLSprite::dummy_tex[] = { 0, 0 };
/* static */ GLuint OpenGLSprite::pal_identity = 0;
/* static */ GLuint OpenGLSprite::pal_tex = 0;
/* static */ GLuint OpenGLSprite::pal_pbo = 0;
* Create all common resources for sprite rendering.
* @return True if no error occurred.
@@ -25,97 +25,97 @@ bool IsOpenGLVersionAtLeast(byte major,
const char *FindStringInExtensionList(const char *string, const char *substring);
class OpenGLSprite;
/** Platform-independent back-end class for OpenGL video drivers. */
class OpenGLBackend : public ZeroedMemoryAllocator, SpriteEncoder {
private:
static OpenGLBackend *instance; ///< Singleton instance pointer.
bool persistent_mapping_supported; ///< Persistent pixel buffer mapping supported.
GLsync sync_vid_mapping; ///< Sync object for the persistently mapped video buffer.
GLsync sync_anim_mapping; ///< Sync object for the persistently mapped animation buffer.
void *vid_buffer; ///< Pointer to the mapped video buffer.
GLuint vid_pbo; ///< Pixel buffer object storing the memory used for the video driver to draw to.
GLuint vid_texture; ///< Texture handle for the video buffer texture.
GLuint vid_program; ///< Shader program for rendering a RGBA video buffer.
GLuint pal_program; ///< Shader program for rendering a paletted video buffer.
GLuint vao_quad; ///< Vertex array object storing the rendering state for the fullscreen quad.
GLuint vbo_quad; ///< Vertex buffer with a fullscreen quad.
GLuint pal_texture; ///< Palette lookup texture.
void *anim_buffer; ///< Pointer to the mapped animation buffer.
GLuint anim_pbo; ///< Pixel buffer object storing the memory used for the animation buffer.
GLuint anim_texture; ///< Texture handle for the animation buffer texture.
GLuint remap_program; ///< Shader program for blending and rendering a RGBA + remap texture.
GLint remap_sprite_loc; ///< Uniform location for sprite parameters.
GLint remap_screen_loc; ///< Uniform location for screen size;
GLint remap_zoom_loc; ///< Uniform location for sprite zoom;
GLint remap_rgb_loc; ///< Uniform location for RGB mode flag;
GLuint sprite_program; ///< Shader program for blending and rendering a sprite to the video buffer.
GLint sprite_sprite_loc; ///< Uniform location for sprite parameters.
GLint sprite_screen_loc; ///< Uniform location for screen size;
GLint sprite_zoom_loc; ///< Uniform location for sprite zoom;
GLint sprite_rgb_loc; ///< Uniform location for RGB mode flag;
GLint sprite_crash_loc; ///< Uniform location for crash remap mode flag;
LRUCache<SpriteID, Sprite> cursor_cache; ///< Cache of encoded cursor sprites.
PaletteID last_sprite_pal = (PaletteID)-1; ///< Last uploaded remap palette.
OpenGLBackend();
~OpenGLBackend();
const char *Init();
bool InitShaders();
void RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, uint x, uint y, ZoomLevel zoom);
void RenderOglSprite(OpenGLSprite *gl_sprite, PaletteID pal, int x, int y, ZoomLevel zoom);
public:
/** Get singleton instance of this class. */
static inline OpenGLBackend *Get()
return OpenGLBackend::instance;
static const char *Create(GetOGLProcAddressProc get_proc);
static void Destroy();
void PrepareContext();
void UpdatePalette(const Colour *pal, uint first, uint length);
bool Resize(int w, int h, bool force = false);
void Paint();
void DrawMouseCursor();
void ClearCursorCache();
void *GetVideoBuffer();
uint8 *GetAnimBuffer();
void ReleaseVideoBuffer(const Rect &update_rect);
void ReleaseAnimBuffer(const Rect &update_rect);
/* SpriteEncoder */
bool Is32BppSupported() override { return true; }
uint GetSpriteAlignment() override { return 1u << (ZOOM_LVL_COUNT - 1); }
Sprite *Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) override;
};
/** Class that encapsulates a RGBA texture together with a paletted remap texture. */
class OpenGLSprite {
/** Enum of all used OpenGL texture objects. */
enum Texture {
TEX_RGBA, ///< RGBA texture part.
TEX_REMAP, ///< Remap texture part.
NUM_TEX
Dimension dim;
GLuint tex[NUM_TEX]; ///< The texture objects.
static GLuint dummy_tex[NUM_TEX]; ///< 1x1 dummy textures to substitute for unused sprite components.
static GLuint pal_identity; ///< Identity texture mapping.
Status change: