diff options
Diffstat (limited to 'modules/librender/g_screen.c')
-rw-r--r-- | modules/librender/g_screen.c | 523 |
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 ) ; + } + } + } +} + +/* --------------------------------------------------------------------------- */ |