aboutsummaryrefslogtreecommitdiff
path: root/modules/librender/g_screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/librender/g_screen.c')
-rw-r--r--modules/librender/g_screen.c523
1 files changed, 523 insertions, 0 deletions
diff --git a/modules/librender/g_screen.c b/modules/librender/g_screen.c
new file mode 100644
index 0000000..4d319fe
--- /dev/null
+++ b/modules/librender/g_screen.c
@@ -0,0 +1,523 @@
+/*
+ * Copyright � 2006-2016 SplinterGU (Fenix/Bennugd)
+ * Copyright � 2002-2006 Fenix Team (Fenix)
+ * Copyright � 1999-2002 Jos� Luis Cebri�n Pag�e (Fenix)
+ *
+ * This file is part of Bennu - Game Development
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "librender.h"
+
+/* --------------------------------------------------------------------------- */
+
+static GRAPH * scrbitmap_extra = NULL ;
+
+static int updaterects_count = 0;
+static REGION updaterects[ DIRTYCOLS * DIRTYROWS ];
+static SDL_Rect rects[ DIRTYCOLS * DIRTYROWS ];
+
+/* --------------------------------------------------------------------------- */
+/*
+ * FUNCTION : gr_draw_screen
+ *
+ * Draw the current screen, using the given restore_type / dump_type parameters
+ *
+ * PARAMS :
+ * dest Destination graphic (MUST have a correct size)
+ *
+ * restore_type
+ * -1 No background restore
+ * 0 Partial (old process bounding box) background restore
+ * 1 Full background restore
+ *
+ * dump_type
+ * 0 Partial (new process bounding box) drawing
+ * 1 Full drawing
+ *
+ * RETURN VALUE :
+ * None
+ */
+
+void gr_draw_screen( GRAPH * dest, int restore_type, int dump_type )
+{
+ int a ;
+ GRAPH * orig_scrbitmap = scrbitmap;
+
+ scrbitmap = dest ;
+
+ if ( background && background->modified )
+ {
+ restore_type = 1;
+ dump_type = 1;
+ }
+
+ /* Update the object list */
+ gr_update_objects_mark_rects( restore_type, dump_type );
+
+ /* Restore the background */
+ if ( !dump_type || !restore_type )
+ {
+ updaterects_count = gr_mark_rects( updaterects );
+ }
+ else
+ {
+ updaterects_count = 1;
+ updaterects[ 0 ].x = 0;
+ updaterects[ 0 ].y = 0;
+ updaterects[ 0 ].x2 = scr_width - 1;
+ updaterects[ 0 ].y2 = scr_height - 1;
+ }
+
+ if ( !restore_type )
+ {
+ /* PARTIAL_RESTORE */
+ if ( background->info_flags & GI_CLEAN )
+ {
+ for ( a = 0; a < updaterects_count; a++ )
+ gr_clear_region( scrbitmap, &updaterects[ a ] );
+ }
+ else
+ {
+ for ( a = 0; a < updaterects_count; a++ )
+ gr_blit( scrbitmap, &updaterects[ a ], 0, 0, B_NOCOLORKEY, background );
+ }
+ }
+ else if ( restore_type == 1 )
+ {
+ /* COMPLETE_RESTORE */
+ if ( background->info_flags & GI_CLEAN )
+ gr_clear( scrbitmap ) ;
+ else
+ gr_blit( scrbitmap, NULL, 0, 0, B_NOCOLORKEY, background );
+
+ updaterects_count = 1;
+ updaterects[ 0 ].x = 0;
+ updaterects[ 0 ].y = 0;
+ updaterects[ 0 ].x2 = scr_width - 1;
+ updaterects[ 0 ].y2 = scr_height - 1;
+ }
+
+ /* Dump the objects */
+ if ( dump_type == 0 )
+ {
+ /* Dump only changed & enabled objects */
+ gr_draw_objects( updaterects, updaterects_count );
+ }
+ else
+ {
+ /* Dump everything */
+ gr_draw_objects_complete();
+ }
+
+ /* Reset the zone-to-update array for the next frame */
+ gr_rects_clear();
+
+ if ( background && background->modified ) background->modified = 0;
+ if ( scrbitmap && scrbitmap->modified ) scrbitmap->modified = 0;
+
+ scrbitmap = orig_scrbitmap;
+}
+
+/* --------------------------------------------------------------------------- */
+
+static int screen_locked = 0 ;
+
+int gr_lock_screen()
+{
+ if ( screen_locked ) return 1 ;
+
+ screen_locked = 1 ;
+
+ if ( scale_resolution != -1 )
+ {
+ if ( SDL_MUSTLOCK( scale_screen ) ) SDL_LockSurface( scale_screen ) ;
+ }
+ else
+ {
+ if ( SDL_MUSTLOCK( screen ) ) SDL_LockSurface( screen ) ;
+ }
+
+ if ( enable_scale || scale_mode != SCALE_NONE )
+ {
+ if ( scrbitmap && ( scrbitmap->info_flags & GI_EXTERNAL_DATA ) )
+ {
+ bitmap_destroy( scrbitmap ) ;
+ scrbitmap = NULL ;
+ }
+
+ if ( !scrbitmap )
+ {
+ scrbitmap = bitmap_new( 0, screen->w / 2, screen->h / 2, sys_pixel_format->depth ) ;
+ bitmap_add_cpoint( scrbitmap, 0, 0 ) ;
+ }
+ }
+ else
+ {
+ if ( !scrbitmap || !( scrbitmap->info_flags & GI_EXTERNAL_DATA ) )
+ {
+ if ( scrbitmap ) bitmap_destroy( scrbitmap ) ;
+ scrbitmap = bitmap_new_ex( 0, screen->w, screen->h, screen->format->BitsPerPixel, screen->pixels, screen->pitch );
+ bitmap_add_cpoint( scrbitmap, 0, 0 ) ;
+ }
+ }
+
+ return 1 ;
+}
+
+/* --------------------------------------------------------------------------- */
+
+void gr_unlock_screen()
+{
+ if ( !screen_locked || !screen->pixels ) return ;
+
+ screen_locked = 0 ;
+
+ if ( scale_resolution != -1 )
+ {
+ uint8_t * src8 = screen->pixels, * dst8 = scale_screen->pixels , * pdst = scale_screen->pixels ;
+ uint16_t * src16 = screen->pixels, * dst16 = scale_screen->pixels ;
+ uint32_t * src32 = screen->pixels, * dst32 = scale_screen->pixels ;
+ int h, w;
+
+ switch ( scale_screen->format->BitsPerPixel )
+ {
+ case 8:
+ if ( scale_resolution_orientation == 1 || scale_resolution_orientation == 3 )
+ {
+ if ( scale_resolution_aspectratio )
+ {
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ if ( scale_resolution_table_w[w] != -1 )
+ {
+ src8 = screen->pixels + scale_resolution_table_w[w];
+ for ( h = scale_screen->h - 1; h-- ; )
+ {
+ if ( scale_resolution_table_h[h] != -1 ) *dst8 = src8[scale_resolution_table_h[h]];
+ dst8 += scale_screen->pitch ;
+ }
+ }
+ dst8 = pdst += scale_screen->format->BytesPerPixel ;
+ }
+ }
+ else
+ {
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ src8 = screen->pixels + scale_resolution_table_w[w];
+ for ( h = scale_screen->h - 1; h-- ; )
+ {
+ *dst8 = src8[scale_resolution_table_h[h]];
+ dst8 += scale_screen->pitch ;
+ }
+ }
+ dst8 = pdst += scale_screen->format->BytesPerPixel ;
+ }
+ }
+ else
+ {
+ if ( scale_resolution_aspectratio )
+ {
+ for ( h = 0; h < scale_screen->h; h++ )
+ {
+ if ( scale_resolution_table_h[h] != -1 )
+ {
+ src8 = screen->pixels + scale_resolution_table_h[h];
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ if ( scale_resolution_table_w[w] != -1 ) *dst8 = src8[scale_resolution_table_w[w]];
+ dst8++;
+ }
+ }
+ dst8 = pdst += scale_screen->pitch ;
+ }
+ }
+ else
+ {
+ for ( h = 0; h < scale_screen->h; h++ )
+ {
+ src8 = screen->pixels + scale_resolution_table_h[h];
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ *dst8 = src8[scale_resolution_table_w[w]];
+ dst8++;
+ }
+ dst8 = pdst += scale_screen->pitch ;
+ }
+ }
+ }
+ break;
+
+ case 16:
+ if ( scale_resolution_orientation == 1 || scale_resolution_orientation == 3 )
+ {
+ if ( scale_resolution_aspectratio )
+ {
+ int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel;
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ if ( scale_resolution_table_w[w] != -1 )
+ {
+ src16 = screen->pixels + scale_resolution_table_w[w];
+ for ( h = scale_screen->h - 1; h-- ; )
+ {
+ if ( scale_resolution_table_h[h] != -1 ) *dst16 = src16[scale_resolution_table_h[h]];
+ dst16 += inc;
+ }
+ }
+ dst16 = ( uint16_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ;
+ }
+ }
+ else
+ {
+ int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel;
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ src16 = screen->pixels + scale_resolution_table_w[w];
+ for ( h = scale_screen->h - 1; h-- ; )
+ {
+ *dst16 = src16[scale_resolution_table_h[h]];
+ dst16 += inc;
+ }
+ dst16 = ( uint16_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ;
+ }
+ }
+ }
+ else
+ {
+ if ( scale_resolution_aspectratio )
+ {
+ for ( h = 0; h < scale_screen->h; h++ )
+ {
+ if ( scale_resolution_table_h[h] != -1 )
+ {
+ src16 = screen->pixels + scale_resolution_table_h[h];
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ if ( scale_resolution_table_w[w] != -1 ) *dst16 = src16[scale_resolution_table_w[w]];
+ dst16++;
+ }
+ }
+ dst16 = ( uint16_t * ) ( pdst += scale_screen->pitch ) ;
+ }
+ }
+ else
+ {
+ for ( h = 0; h < scale_screen->h; h++ )
+ {
+ src16 = screen->pixels + scale_resolution_table_h[h];
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ *dst16 = src16[scale_resolution_table_w[w]];
+ dst16++;
+ }
+ dst16 = ( uint16_t * ) ( pdst += scale_screen->pitch ) ;
+ }
+ }
+ }
+ break;
+
+ case 32:
+ if ( scale_resolution_orientation == 1 || scale_resolution_orientation == 3 )
+ {
+ if ( scale_resolution_aspectratio )
+ {
+ int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel;
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ if ( scale_resolution_table_w[w] != -1 )
+ {
+ src32 = screen->pixels + scale_resolution_table_w[w];
+ for ( h = scale_screen->h - 1; h-- ; )
+ {
+ if ( scale_resolution_table_h[h] != -1 ) *dst32 = src32[scale_resolution_table_h[h]];
+ dst32 += inc;
+ }
+ }
+ dst32 = ( uint32_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ;
+ }
+ }
+ else
+ {
+ int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel;
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ src32 = screen->pixels + scale_resolution_table_w[w];
+ for ( h = scale_screen->h - 1; h-- ; )
+ {
+ *dst32 = src32[scale_resolution_table_h[h]];
+ dst32 += inc;
+ }
+ dst32 = ( uint32_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ;
+ }
+ }
+ }
+ else
+ {
+ if ( scale_resolution_aspectratio )
+ {
+ for ( h = 0; h < scale_screen->h; h++ )
+ {
+ if ( scale_resolution_table_h[h] != -1 )
+ {
+ src32 = screen->pixels + scale_resolution_table_h[h];
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ if ( scale_resolution_table_w[w] != -1 ) *dst32 = src32[scale_resolution_table_w[w]];
+ dst32++;
+ }
+ }
+ dst32 = ( uint32_t * ) ( pdst += scale_screen->pitch ) ;
+ }
+ }
+ else
+ {
+ for ( h = 0; h < scale_screen->h; h++ )
+ {
+ src32 = screen->pixels + scale_resolution_table_h[h];
+ for ( w = 0; w < scale_screen->w; w++ )
+ {
+ *dst32 = src32[scale_resolution_table_w[w]];
+ dst32++;
+ }
+ dst32 = ( uint32_t * ) ( pdst += scale_screen->pitch ) ;
+ }
+ }
+ }
+ break;
+ }
+
+ if ( SDL_MUSTLOCK( scale_screen ) ) SDL_UnlockSurface( scale_screen ) ;
+ if ( waitvsync ) gr_wait_vsync();
+ SDL_Flip( scale_screen ) ;
+ }
+ else if ( enable_scale )
+ {
+ GRAPH * scr;
+
+ if ( scrbitmap->format->depth == 8 )
+ {
+ uint8_t * original, * poriginal;
+ uint16_t * extra, * pextra;
+ int n = scrbitmap->height, length;
+
+ if (
+ !scrbitmap_extra ||
+ scrbitmap_extra->width != scrbitmap->width ||
+ scrbitmap_extra->height != scrbitmap->height
+ )
+ {
+ if ( scrbitmap_extra ) bitmap_destroy( scrbitmap_extra );
+ scrbitmap_extra = bitmap_new( 0, scrbitmap->width, scrbitmap->height, 16 );
+ }
+
+ poriginal = scrbitmap->data;
+ pextra = scrbitmap_extra->data;
+
+ while ( n-- )
+ {
+ original = poriginal;
+ extra = pextra;
+ length = scrbitmap->width;
+ while ( length-- ) *extra++ = sys_pixel_format->palette->colorequiv[ *original++ ];
+ poriginal += scrbitmap->pitch;
+ pextra = ( uint16_t * )((( uint8_t * ) pextra ) + scrbitmap_extra->pitch );
+ }
+
+ scr = scrbitmap_extra;
+ }
+ else
+ {
+ scr = scrbitmap;
+ }
+
+ /* Esto podria ir en un modulo aparte */
+ switch ( scale_mode )
+ {
+ case SCALE_SCALE2X:
+ scale2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height );
+ break;
+
+ case SCALE_HQ2X:
+ hq2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height );
+ break;
+
+ case SCALE_SCANLINE2X:
+ scanline2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height );
+ break;
+
+ case SCALE_NOFILTER:
+ scale_normal2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height );
+ break;
+
+ case SCALE_NONE:
+ // No usado
+ break;
+ }
+
+ if ( SDL_MUSTLOCK( screen ) ) SDL_UnlockSurface( screen ) ;
+ if ( waitvsync ) gr_wait_vsync();
+ SDL_Flip( screen ) ;
+ }
+ else if ( scrbitmap->info_flags & GI_EXTERNAL_DATA )
+ {
+ if ( double_buffer ||
+ (
+ updaterects_count == 1 &&
+ updaterects[0].x == 0 &&
+ updaterects[0].y == 0 &&
+ updaterects[0].x2 == scr_width - 1 &&
+ updaterects[0].y2 == scr_height - 1
+ )
+ )
+ {
+ if ( SDL_MUSTLOCK( screen ) ) SDL_UnlockSurface( screen ) ;
+ if ( waitvsync ) gr_wait_vsync();
+ SDL_Flip( screen ) ;
+ }
+ else
+ {
+ if ( updaterects_count )
+ {
+ int i;
+
+ for ( i = 0 ; i < updaterects_count ; i++ )
+ {
+ rects[ i ].x = updaterects[ i ].x;
+ rects[ i ].y = updaterects[ i ].y;
+ rects[ i ].w = ( updaterects[ i ].x2 - rects[ i ].x + 1 );
+ rects[ i ].h = ( updaterects[ i ].y2 - rects[ i ].y + 1 );
+ }
+ if ( SDL_MUSTLOCK( screen ) ) SDL_UnlockSurface( screen ) ;
+ if ( waitvsync ) gr_wait_vsync();
+ SDL_UpdateRects( screen, updaterects_count, rects ) ;
+ }
+ }
+ }
+}
+
+/* --------------------------------------------------------------------------- */