| author | Tomi 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) |
| commit | aea25f12db99f0a88251d96b0d254dd0a4138ae3 (patch) | |
| tree | cce9b10303d968f045d09de8aa823d383ae81c4e | |
| parent | 23d43a2851351ac42bae2b68289c6470f77c3632 (diff) | |
| download | rocksndiamonds-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.
| -rw-r--r-- | src/libgame/sdl.c | 160 |
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 */ |
