Changeset - r24963:38bc5b49d3a7
[Not reviewed]
master
0 2 0
Michael Lutz - 3 years ago 2021-02-28 09:58:56
michi@icosahedron.de
Fix #8763: [OpenGL] Cursor sprite origin can be negative.
2 files changed with 2 insertions and 2 deletions:
0 comments (0 inline, 0 general)
src/video/opengl.cpp
Show inline comments
 
@@ -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));
 

	
 
#ifndef NO_GL_BUFFER_SYNC
 
		if (this->persistent_mapping_supported) this->sync_anim_mapping = _glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 
#endif
 
	}
 
}
 

	
 
/* 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.
src/video/opengl.h
Show inline comments
 
@@ -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 {
 
private:
 
	/** 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.
0 comments (0 inline, 0 general)