summaryrefslogtreecommitdiff
authorTomi Belan <tomi.belan@gmail.com>2010-02-16 19:35:01 (GMT)
committer Tomi Belan <tomi.belan@gmail.com>2010-02-16 19:35:01 (GMT)
commitaea25f12db99f0a88251d96b0d254dd0a4138ae3 (patch)
treecce9b10303d968f045d09de8aa823d383ae81c4e
parent23d43a2851351ac42bae2b68289c6470f77c3632 (diff)
downloadrocksndiamonds-master.zip
rocksndiamonds-master.tar.gz
rocksndiamonds-master.tar.bz2
add support for texture-to-texture blits.master
per Holger's suggestion, texture-to-texture blits are implemented as texture-to-framebuffer followed by framebuffer-to-texture blits.
Diffstat
-rw-r--r--src/libgame/sdl.c160
1 files changed, 71 insertions, 89 deletions
diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c
index 29e2254..96c3a99 100644
--- a/src/libgame/sdl.c
+++ b/src/libgame/sdl.c
@@ -213,11 +213,8 @@ void SDLInitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
/* set window and icon title */
SDL_WM_SetCaption(program.window_title, program.window_title);
- /* create additional (symbolic) buffer for double-buffering */
- /* GL-TODO: remove all uses of 'window'. 'window' is never drawn to.
- * the only reason we create a Bitmap and not just use '*window = NULL'
- * is that a lot of code still uses 'window == NULL' to check if video
- * is available. */
+ /* create additional (symbolic) buffers for double-buffering */
+ *backbuffer = CreateBitmap(video.width, video.height, video.depth);
*window = CreateBitmapStruct();
}
@@ -229,9 +226,6 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
int video_yoffset_bottom;
SDL_Surface *new_surface = NULL;
- if (*backbuffer == NULL)
- *backbuffer = CreateBitmapStruct();
-
/* GL-TODO: this should be placed immediately before SDL_SetVideoMode. */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
@@ -258,8 +252,6 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
}
else
{
- (*backbuffer)->surface = new_surface;
-
video.fullscreen_enabled = TRUE;
video.fullscreen_mode_current = setup.fullscreen_mode;
@@ -285,8 +277,6 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
}
else
{
- (*backbuffer)->surface = new_surface;
-
video.fullscreen_enabled = FALSE;
success = TRUE;
}
@@ -294,7 +284,7 @@ boolean SDLSetVideoMode(DrawBuffer **backbuffer, boolean fullscreen)
if (success)
{
- glClearColor(0, 0, 0, 0);
+ glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(video_xoffset, video_yoffset_bottom, video.width, video.height);
glMatrixMode(GL_PROJECTION); glLoadIdentity();
@@ -354,7 +344,9 @@ void SDLCreateBitmapContent(Bitmap *new_bitmap, int width, int height,
depth = 4;
/* GL-TODO: is it possible to set size without allocating this memory? */
pixels = checked_calloc(realw * realh * depth); /* zeroes */
+#if 0
memset(pixels, 128, realw * realh * depth); /* GL-TODO: REMOVE DEBUG */
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, depth, realw, realh, 0,
depth == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, pixels);
checked_free(pixels);
@@ -382,60 +374,23 @@ void SDLFreeBitmapPointers(Bitmap *bitmap)
bitmap->texture_name = 0;
}
-void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
- int src_x, int src_y, int width, int height,
- int dst_x, int dst_y, int mask_mode)
+static void SDLBlitToWindow(Bitmap *src_bitmap,
+ int src_x, int src_y, int width, int height,
+ int dst_x, int dst_y, int mask_mode)
{
- if (dst_bitmap != backbuffer && dst_bitmap != window)
- {
- if (src_bitmap == backbuffer)
- {
- if (dst_bitmap->texture_name == 0)
- return;
- glBindTexture(GL_TEXTURE_2D, dst_bitmap->texture_name);
- /* GL-TODO: this assumes video_yoffset is the same on the top and
- * the bottom of the screen. is that correct? (i.e. are video.height
- * and fullscreen_height always even?) */
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
- dst_x, dst_bitmap->height - dst_y - height,
- src_x + video_xoffset, video.height + video_yoffset - src_y - height,
- width, height);
- }
- else
- {
- Error(ERR_WARN, "SDLCopyArea() from bitmap to bitmap is deprecated");
- }
- return;
- }
-
- if (src_bitmap == backbuffer && dst_bitmap == window)
- {
- SDL_GL_SwapBuffers();
-#if 0
- /* this draws a yellow layer on the backbuffer, showing which regions
- * of the screen were recently redrawn. if the whole screen was always
- * redrawn, no yellow layer would be visible. */
- glBindTexture(GL_TEXTURE_2D, 0);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(1, 1, 0, 0.01);
- glBegin(GL_QUADS);
- glVertex2i(0, 0); glVertex2i(800, 0); glVertex2i(800, 600); glVertex2i(0, 600);
- glEnd();
-#endif
- return;
- }
-
if(src_bitmap->texture_name == 0)
return;
- if (mask_mode == BLIT_MASKED)
+ if (mask_mode == BLIT_MASKED || mask_mode == BLIT_INVERSE)
glEnable(GL_BLEND);
else
glDisable(GL_BLEND);
/* GL-TODO: don't allow blitting from outside src_bitmap */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, src_bitmap->texture_name);
- glColor3f(1, 1, 1); /* GL-TODO: allow black for SDLCopyInverseMasked */
+ if (mask_mode == BLIT_INVERSE)
+ glColor3f(0, 0, 0);
+ else
+ glColor3f(1, 1, 1);
glBegin(GL_QUADS);
/* all the Vertex() arguments are in traditional coordinates (0 is up). */
#define Vertex(sx, sy, dx, dy) \
@@ -448,31 +403,78 @@ void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
Vertex(src_x, src_y, dst_x, dst_y); /* upper left */
#undef Vertex
glEnd();
+}
+
+static void SDLBlitFromWindow(Bitmap *dst_bitmap,
+ int src_x, int src_y, int width, int height,
+ int dst_x, int dst_y)
+{
+ if (dst_bitmap->texture_name == 0)
+ return;
+ glBindTexture(GL_TEXTURE_2D, dst_bitmap->texture_name);
+ /* GL-TODO: this assumes video_yoffset is the same on the top and
+ * the bottom of the screen. is that correct? (i.e. are video.height
+ * and fullscreen_height always even?) */
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
+ dst_x, dst_bitmap->height - dst_y - height,
+ src_x + video_xoffset, video.height + video_yoffset - src_y - height,
+ width, height);
+}
- if (dst_bitmap == window)
+void SDLCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+ int src_x, int src_y, int width, int height,
+ int dst_x, int dst_y, int mask_mode)
+{
+ Bitmap *real_dst_bitmap = (dst_bitmap == window ? backbuffer : dst_bitmap);
+
+ if (src_bitmap != backbuffer || dst_bitmap != window) {
+ if (mask_mode == BLIT_OPAQUE)
+ SDLBlitToWindow(src_bitmap, src_x, src_y, width, height, 0, 0, BLIT_OPAQUE);
+ else {
+ SDLBlitToWindow(real_dst_bitmap, dst_x, dst_y, width, height, 0, 0, BLIT_OPAQUE);
+ SDLBlitToWindow(src_bitmap, src_x, src_y, width, height, 0, 0, mask_mode);
+ }
+ SDLBlitFromWindow(real_dst_bitmap, 0, 0, width, height, dst_x, dst_y);
+ }
+ if (dst_bitmap == window) {
+ /* window is used as a temporary buffer for blits, so partial screen updates
+ * aren't supported */
+ SDLBlitToWindow(backbuffer, 0, 0, video.width, video.height, 0, 0, BLIT_OPAQUE);
SDL_GL_SwapBuffers();
+#if 1
+ /* this draws a yellow layer on the backbuffer, showing which regions
+ * of the screen were recently redrawn. if the whole screen was always
+ * redrawn, no yellow layer would be visible. */
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(1, 1, 0, 0.01);
+ glBegin(GL_QUADS);
+ glVertex2i(0, 0); glVertex2i(800, 0); glVertex2i(800, 600); glVertex2i(0, 600);
+ glEnd();
+#endif
+ }
}
void SDLFillRectangle(Bitmap *dst_bitmap, int x, int y, int width, int height,
Uint32 color)
{
- if (dst_bitmap != backbuffer && dst_bitmap != window)
+ if (dst_bitmap != backbuffer)
{
- Error(ERR_WARN, "SDLFilLRectangle() to a bitmap is deprecated");
+ Error(ERR_WARN, "SDLFillRectangle() to bitmaps other than backbuffer is deprecated");
return;
}
glBindTexture(GL_TEXTURE_2D, 0);
glColor3ub((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
glBegin(GL_QUADS);
- glVertex2i(x, video.height-y);
- glVertex2i(x+width, video.height-y);
- glVertex2i(x+width, video.height-y-height);
- glVertex2i(x, video.height-y-height);
+ glVertex2i(0, 0);
+ glVertex2i(0, video.height);
+ glVertex2i(video.width, video.height);
+ glVertex2i(video.width, 0);
glEnd();
- if (dst_bitmap == window)
- SDL_GL_SwapBuffers();
+ SDLBlitFromWindow(backbuffer, 0, 0, width, height, x, y);
}
void SDLFadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
@@ -738,21 +740,7 @@ void SDLDrawSimpleLine(Bitmap *dst_bitmap, int from_x, int from_y,
void SDLDrawLine(Bitmap *dst_bitmap, int from_x, int from_y,
int to_x, int to_y, Uint32 color)
{
- if (dst_bitmap != backbuffer && dst_bitmap != window)
- {
- Error(ERR_WARN, "SDLDrawLine() to a bitmap is deprecated");
- return;
- }
-
- glBindTexture(GL_TEXTURE_2D, 0);
- glColor3ub((color>>16)&0xFF, (color>>8)&0xFF, color&0xFF);
- glBegin(GL_LINES);
- glVertex2i(from_x, video.height-from_y);
- glVertex2i(to_x, video.height-to_y);
- glEnd();
-
- if (dst_bitmap == window)
- SDL_GL_SwapBuffers();
+ Error(ERR_WARN, "SDLDrawLine() is deprecated");
}
Pixel SDLGetPixel(Bitmap *src_bitmap, int x, int y)
@@ -777,12 +765,7 @@ void SDLCopyInverseMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
int src_x, int src_y, int width, int height,
int dst_x, int dst_y)
{
- Error(ERR_WARN, "SDLCopyInverseMasked() is deprecated");
- /* GL-TODO: implement this.
- * for each non-black pixel in src_bitmap, this function draws a black
- * pixel in dst_bitmap. this is used for text cursors in DrawTextExt.
- * this can be trivially reimplemented by setting glColor to black
- * before doing BlitBitmap, but SDLCopyArea sets glColor(1,1,1) ATM. */
+ SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height, dst_x, dst_y, BLIT_INVERSE);
}
void SDLZoomBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap)
@@ -869,7 +852,6 @@ Bitmap *SDLLoadImage(char *filename)
{
for (x = 0; x < sdl_image_tmp->w; x++)
{
- Uint8 pixel[4];
SDL_GetRGBA(SDLGetSurfacePixel(sdl_image_tmp, x, y), sdl_image_tmp->format,
line+x*4+0, line+x*4+1, line+x*4+2, line+x*4+3);
/* simulate colorkey */