From 3617e8e7a105b0bfab6f9b48b48848c2bb592a56 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 25 Mar 2019 03:34:30 +0700 Subject: [PATCH] ref_soft: REF_SOFTWARE, resize support --- r_context.c | 2 +- r_draw.c | 4 +- r_glblit.c | 172 ++++++++++++++++++++++++++++++++++++++++++---------- r_local.h | 5 +- r_main.c | 14 ++--- r_surf.c | 13 +++- 6 files changed, 165 insertions(+), 45 deletions(-) diff --git a/r_context.c b/r_context.c index 65821e7c..9f71afae 100644 --- a/r_context.c +++ b/r_context.c @@ -326,7 +326,7 @@ void GL_SetTexCoordArrayMode() void GL_OnContextCreated() { - R_InitBlit(); + //R_InitBlit(); } diff --git a/r_draw.c b/r_draw.c index 26f9cbe9..2f6fb211 100644 --- a/r_draw.c +++ b/r_draw.c @@ -118,11 +118,13 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, #pragma omp parallel for schedule(static) for (v=0 ; vwidth + s1; + { f = 0; fstep = s2*0x10000/w; @@ -144,7 +146,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, for (u=0 ; u>16]; - int alpha = vid.alpha; + int alpha = alpha1; f += fstep; if( transparent ) diff --git a/r_glblit.c b/r_glblit.c index f3eb4f1d..7b57a68e 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -1,6 +1,13 @@ #include "r_local.h" #include "../ref_gl/gl_export.h" +struct swblit_s +{ + uint stride; + uint bpp; + uint rmask, gmask, bmask; +} swblit; + /* ======================== @@ -38,9 +45,35 @@ unsigned short *buffer; #define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) -void R_BuildScreenMap() +static int FIRST_BIT( uint mask ) +{ + uint i; + + for( i = 0; !(BIT(i) & mask); i++ ); + + return i; +} + +static int COUNT_BITS( uint mask ) +{ + uint i; + + for( i = 0; mask; mask = mask >> 1 ) + i += mask & 1; + + return i; +} + +void R_BuildScreenMap( void ) { int i; + uint rshift = FIRST_BIT(swblit.rmask), gshift = FIRST_BIT(swblit.gmask), bshift = FIRST_BIT(swblit.bmask); + uint rbits = COUNT_BITS(swblit.rmask), gbits = COUNT_BITS(swblit.gmask), bbits = COUNT_BITS(swblit.bmask); + uint rmult = BIT(rbits), gmult = BIT(gbits), bmult = BIT(bbits); + uint rdiv = MASK(5), gdiv = MASK(6), bdiv = MASK(5); + + gEngfuncs.Con_Printf("Blit table: %d %d %d %d %d %d\n", rmult, gmult, bmult, rdiv, gdiv, bdiv ); + #ifdef SEPARATE_BLIT for( i = 0; i < 256; i++ ) { @@ -69,16 +102,24 @@ void R_BuildScreenMap() r = ((i >> (8 - 3) )<< 2 ) & MASK(5); g = ((i >> (8 - 3 - 3)) << 3) & MASK(6); b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5); - major = r << (6 + 5) | (g << 5) | b; + //major = r << (6 + 5) | (g << 5) | b; + major = (r * rmult / rdiv) << rshift | (g * gmult / gdiv) << gshift | (b * bmult / bdiv) << bshift; for( j = 0; j < 256; j++ ) { + uint minor; // restore minor GBRGBRGB r = MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0); g = MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0); b = MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); - vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major; + //vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major; + minor = (r * rmult / rdiv) << rshift | (g * gmult / gdiv) << gshift | (b * bmult / bdiv) << bshift; + + if( swblit.bpp == 2 ) + vid.screen[(i<<8)|j] = major | minor; + else + vid.screen32[(i<<8)|j] = major | minor; } @@ -103,18 +144,18 @@ void R_BuildBlendMaps() r = r1 + r2; g = g1 + g2; b = b1 + b2; - if( r > MASK(2) ) - r = MASK(2); - if( g > MASK(2) ) - g = MASK(2); - if( b > MASK(1) ) - b = MASK(1); + if( r > MASK(3) ) + r = MASK(3); + if( g > MASK(3) ) + g = MASK(3); + if( b > MASK(2) ) + b = MASK(2); ASSERT(!vid.addmap[index2|index1]); vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b; - r = r1 * r2 / MASK(2); - g = g1 * g2 / MASK(2); - b = b1 * b2 / MASK(1); + r = r1 * r2 / MASK(3); + g = g1 * g2 / MASK(3); + b = b1 * b2 / MASK(2); vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; @@ -130,10 +171,12 @@ void R_BuildBlendMaps() } } +void R_AllocScreen(); + void R_InitBlit() { - LOAD(glBegin); + /*LOAD(glBegin); LOAD(glEnd); LOAD(glTexCoord2f); LOAD(glVertex2f); @@ -149,7 +192,7 @@ void R_InitBlit() LOAD(glDebugMessageControlARB); LOAD(glGetError); LOAD(glGenTextures); - LOAD(glTexParameteri); + LOAD(glTexParameteri);*/ #ifdef GLDEBUG if( gpGlobals->developer ) { @@ -164,36 +207,100 @@ void R_InitBlit() pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); #endif - buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); + //buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); - R_BuildScreenMap(); R_BuildBlendMaps(); - d_pzbuffer = malloc(vid.width*vid.height*2); - R_InitCaches(); + R_AllocScreen(); +} + +void R_AllocScreen() +{ + if( gpGlobals->width < 320 ) + gpGlobals->width = 320; + if( gpGlobals->height < 200 ) + gpGlobals->height = 200; + R_InitCaches(); + gEngfuncs.SW_CreateBuffer( gpGlobals->width, gpGlobals->height, &swblit.stride, &swblit.bpp, + &swblit.rmask, &swblit.gmask, &swblit.bmask); + R_BuildScreenMap(); + vid.width = gpGlobals->width; + vid.height = gpGlobals->height; + vid.rowbytes = gpGlobals->width; // rowpixels + if( d_pzbuffer ) + Mem_Free( d_pzbuffer ); + d_pzbuffer = Mem_Calloc( r_temppool, vid.width*vid.height*2 + 64 ); + if( vid.buffer ) + Mem_Free( vid.buffer ); + + vid.buffer = Mem_Malloc( r_temppool, vid.width * vid.height*sizeof( pixel_t ) ); } void R_BlitScreen() { //memset( vid.buffer, 10, vid.width * vid.height ); - int i; - byte *buf = vid.buffer; + int u, v; + void *buffer = gEngfuncs.SW_LockBuffer(); + if( !buffer || gpGlobals->width != vid.width || gpGlobals->height != vid.height ) + { + R_AllocScreen(); + return; + } + //byte *buf = vid.buffer; - #pragma omp parallel for schedule(static) - for( i = 0; i < vid.width * vid.height;i++) + //#pragma omp parallel for schedule(static) + if( swblit.bpp == 2 ) { -#ifdef SEPARATE_BLIT - // need only 1024 bytes table, but slower - // wtf?? maybe some prefetch??? - byte major = buf[(i<<1)+1]; - byte minor = buf[(i<<1)]; + unsigned short *pbuf = buffer; + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen[vid.buffer[start + u]]; + pbuf[dstart + u] = s; + } + } + } + else if( swblit.bpp == 4 ) + { + unsigned int *pbuf = buffer; - buffer[i] = vid.screen_major[major] |vid.screen_minor[minor]; -#else - buffer[i] = vid.screen[vid.buffer[i]]; -#endif + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[dstart + u] = s; + } + } + } + else if( swblit.bpp == 3 ) + { + byte *pbuf = buffer; + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[(dstart+u)*3] = s; + s = s >> 8; + pbuf[(dstart+u)*3+1] = s; + s = s >> 8; + pbuf[(dstart+u)*3+2] = s; + } + } } +#if 0 pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); @@ -223,4 +330,7 @@ void R_BlitScreen() pglDisable( GL_TEXTURE_2D ); gEngfuncs.GL_SwapBuffers(); // memset( vid.buffer, 0, vid.width * vid.height * 2 ); +#else + gEngfuncs.SW_UnlockBuffer(); +#endif } diff --git a/r_local.h b/r_local.h index 4f034351..eab47d4d 100644 --- a/r_local.h +++ b/r_local.h @@ -93,7 +93,7 @@ extern byte *r_temppool; #define CULL_OTHER 4 // culled by other reason // bit operation helpers -#define MASK(x) (BIT(x+1)-1) +#define MASK(x) (BIT(x)-1) #define GET_BIT(s,b) ((s & (1 << b)) >> b) #define MOVE_BIT(s, f, t) (GET_BIT(s,f) << t ) @@ -140,6 +140,7 @@ typedef struct pixel_t screen_major[256]; #else pixel_t screen[256*256]; + unsigned int screen32[256*256]; #endif byte addmap[256*256]; byte modmap[256*256]; @@ -832,7 +833,7 @@ extern cvar_t *r_showhull; #define NEAR_CLIP 0.01 -#define MAXALIASVERTS 2000 // TODO: tune this +//#define MAXALIASVERTS 2000 // TODO: tune this #define ALIAS_Z_CLIP_PLANE 4 // turbulence stuff diff --git a/r_main.c b/r_main.c index 5521419d..64b3b329 100644 --- a/r_main.c +++ b/r_main.c @@ -458,7 +458,7 @@ static void R_Clear( int bitMask ) pglDepthFunc( GL_LEQUAL ); pglDepthRange( gldepthmin, gldepthmax ); #endif - memset( vid.buffer, 0, 1920*1080*2); + memset( vid.buffer, 0, vid.width * vid.height *2); } //============================================================================= @@ -1686,6 +1686,10 @@ int R_RenderFrame( const ref_viewpass_t *rvp ) if( r_norefresh->value ) return 1; + // prevent cache overrun + if( gpGlobals->height > vid.height || gpGlobals->width > vid.width ) + return 1; + // setup the initial render params R_SetupRefParams( rvp ); @@ -1842,12 +1846,7 @@ qboolean R_Init() // create the window and set up the context r_temppool = Mem_AllocPool( "ref_sw zone" ); - vid.width = 1920; - vid.height = 1080; - vid.rowbytes = 1920; // rowpixels - - vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); - if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context + if( !gEngfuncs.R_Init_Video( REF_SOFTWARE )) // request GL context { gEngfuncs.R_Free_Video(); @@ -1855,6 +1854,7 @@ qboolean R_Init() return false; } + R_InitBlit(); R_InitImages(); // init draw stack diff --git a/r_surf.c b/r_surf.c index 35503974..19a7edda 100644 --- a/r_surf.c +++ b/r_surf.c @@ -256,6 +256,8 @@ void R_DrawSurface (void) pcolumndest += horzblockstep; } + // test what if we have very slow cache building + //usleep(10000); } @@ -490,9 +492,9 @@ void R_InitCaches (void) } else { - size = SURFCACHE_SIZE_AT_320X240; + size = SURFCACHE_SIZE_AT_320X240 * 2; - pix =1920 * 1080 * 16; + pix = vid.width * vid.height * 2; if (pix > 64000) size += (pix-64000)*3; } @@ -503,7 +505,12 @@ void R_InitCaches (void) gEngfuncs.Con_Printf ("%ik surface cache\n", size/1024); sc_size = size; - sc_base = (surfcache_t *)malloc(size); + if( sc_base ) + { + D_FlushCaches(); + Mem_Free( sc_base ); + } + sc_base = (surfcache_t *)Mem_Calloc(r_temppool,size); sc_rover = sc_base; sc_base->next = NULL;