diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index a49a3bd36..b425cce54 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -115,6 +115,9 @@ typedef struct vid_render_funcs_s { void (*set_2d) (int scaled); void (*end_frame) (void); + struct framebuffer_s *(*create_frame_buffer) (int width, int height); + void (*bind_framebuffer) (struct framebuffer_s *framebuffer); + vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/QF/render.h b/include/QF/render.h index bffec3a85..ed1d66b94 100644 --- a/include/QF/render.h +++ b/include/QF/render.h @@ -191,6 +191,16 @@ typedef union refframe_s { }; } refframe_t; +/** Generic frame buffer object. + * + * For attaching scene cameras to render targets. + */ +typedef struct framebuffer_s { + unsigned width; + unsigned height; + void *buffer; ///< renderer-specific frame buffer data +} framebuffer_t; + // !!! if this is changed, it must be changed in asm_draw.h too !!! typedef struct { vrect_t vrect; // subwindow in video for refresh diff --git a/include/QF/scene/camera.h b/include/QF/scene/camera.h index a7da8412b..5584f397c 100644 --- a/include/QF/scene/camera.h +++ b/include/QF/scene/camera.h @@ -41,6 +41,7 @@ typedef struct camera_s { struct scene_s *scene; ///< owning scene + struct framebuffer_s *framebuffer; int32_t id; ///< id in scene int32_t transform; float field_of_view; diff --git a/include/QF/vid.h b/include/QF/vid.h index c5fd95751..c8ce3b226 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -37,9 +37,6 @@ typedef struct { qboolean initialized; qboolean is8bit; - void *buffer; // invisible buffer - short *zbuffer; - void *surfcache; byte *gammatable; // 256 const byte *basepal; // 256 * 3 byte *palette; // 256 * 3 @@ -48,7 +45,6 @@ typedef struct { unsigned short *colormap16; // 256 * VID_GRADES size unsigned int *colormap32; // 256 * VID_GRADES size int fullbright; // index of first fullbright color - int rowbytes; // may be > width if displayed in a window unsigned width; unsigned height; int numpages; diff --git a/include/d_iface.h b/include/d_iface.h index 4e78c43e8..7f12523ac 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -226,6 +226,4 @@ extern float r_skytime; extern int c_surf; -extern byte *r_warpbuffer; - #endif // _D_IFACE_H diff --git a/include/d_local.h b/include/d_local.h index 042ce2919..51a2cd220 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -104,8 +104,13 @@ void D_PolysetAff8Start (void); void D_PolysetAff8End (void); #endif +extern byte *d_viewbuffer; +extern int d_rowbytes; +extern unsigned d_height; + extern short *d_zbuffer; -extern int d_zrowbytes, d_zwidth; +extern int d_zrowbytes; +extern unsigned d_zwidth; extern int *d_pscantable; extern int d_scantable[]; @@ -114,8 +119,6 @@ extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; -extern byte *d_viewbuffer; - extern short *zspantable[]; extern int d_minmip; diff --git a/include/quakeasm.h b/include/quakeasm.h index 16567c31d..a3657fdc0 100644 --- a/include/quakeasm.h +++ b/include/quakeasm.h @@ -93,7 +93,7 @@ .extern C(d_pix_min) .extern C(d_pix_max) .extern C(d_y_aspect_shift) - .extern C(screenwidth) + .extern C(d_rowbytes) .extern C(r_leftclipped) .extern C(r_leftenter) .extern C(r_rightclipped) diff --git a/include/r_local.h b/include/r_local.h index 0c7a7129e..0b15583ae 100644 --- a/include/r_local.h +++ b/include/r_local.h @@ -270,8 +270,6 @@ extern edge_t *r_edges, *edge_p, *edge_max; extern edge_t *newedges[MAXHEIGHT]; extern edge_t *removeedges[MAXHEIGHT]; -extern int screenwidth; - extern int r_bmodelactive; extern vrect_t *pconupdate; diff --git a/include/r_shared.h b/include/r_shared.h index 843978033..2251a7b1d 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -54,7 +54,6 @@ extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1); extern int cachewidth; extern byte *cacheblock; -extern int screenwidth; extern int r_init; extern float pixelAspect; diff --git a/include/vid_gl.h b/include/vid_gl.h index 618e89d44..8b82ae069 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -19,6 +19,12 @@ typedef struct gl_ctx_s { int alias_polys; } gl_ctx_t; +typedef struct gl_framebuffer_s { + unsigned handle; + unsigned color; + unsigned depth; +} gl_framebuffer_t; + extern gl_ctx_t *gl_ctx; extern gl_ctx_t *glsl_ctx; diff --git a/include/vid_sw.h b/include/vid_sw.h index a43a1a9a2..ed2f21a1a 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -1,14 +1,23 @@ #ifndef __vid_sw_h #define __vid_sw_h +#include "QF/qtypes.h" + struct vrect_s; typedef struct sw_ctx_s { void (*choose_visual) (struct sw_ctx_s *ctx); void (*create_context) (struct sw_ctx_s *ctx); void (*set_palette) (struct sw_ctx_s *ctx, const byte *palette); void (*update) (struct sw_ctx_s *ctx, struct vrect_s *rects); + struct framebuffer_s *framebuffer; } sw_ctx_t; +typedef struct sw_framebuffer_s { + byte *color; + short *depth; + int rowbytes; +} sw_framebuffer_t; + extern sw_ctx_t *sw_ctx; struct tex_s *sw_SCR_CaptureBGR (void); diff --git a/libs/video/renderer/r_main.c b/libs/video/renderer/r_main.c index e9184c80f..846a57dad 100644 --- a/libs/video/renderer/r_main.c +++ b/libs/video/renderer/r_main.c @@ -45,6 +45,7 @@ #include "r_internal.h" +qboolean r_dowarp, r_dowarpold; qboolean r_inhibit_viewmodel; qboolean r_force_fullscreen; qboolean r_paused; diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index 77fdeb411..7089b0cc9 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -66,6 +66,7 @@ static qboolean scr_initialized;// ready to draw static qpic_t *scr_ram; static qpic_t *scr_turtle; +static framebuffer_t *warp_buffer; static void set_vrect (const vrect_t *vrectin, vrect_t *vrect, int lineadj) { @@ -197,11 +198,21 @@ SCR_UpdateScreen (transform_t *camera, double realtime, SCR_Func *scr_funcs) if (refdef->worldmodel) { vec4f_t position = refdef->frame.position; refdef->viewleaf = Mod_PointInLeaf (&position[0], refdef->worldmodel); + r_dowarpold = r_dowarp; + if (r_waterwarp->int_val) { + r_dowarp = refdef->viewleaf->contents <= CONTENTS_WATER; + } + if (r_dowarp && !warp_buffer) { + warp_buffer = r_funcs->create_frame_buffer (r_data->vid->width, r_data->vid->height); + } } R_MarkLeaves (); R_PushDlights (vec3_origin); r_funcs->begin_frame (); + if (r_dowarp) { + r_funcs->bind_framebuffer (warp_buffer); + } r_funcs->render_view (); r_funcs->draw_entities (r_ent_queue); r_funcs->draw_particles (&r_psystem); diff --git a/libs/video/renderer/sw/d_draw.S b/libs/video/renderer/sw/d_draw.S index 012b9a281..cf97cacaa 100644 --- a/libs/video/renderer/sw/d_draw.S +++ b/libs/video/renderer/sw/d_draw.S @@ -194,7 +194,7 @@ LSpanLoop: movl C(tadjust),%edx movl C(sadjust),%esi - movl C(d_scantable)(,%eax,4),%edi // v * screenwidth + movl C(d_scantable)(,%eax,4),%edi // v * d_rowbytes addl %ecx,%edi movl espan_t_u(%ebx),%ecx addl %ecx,%edi // pdest = &pdestspan[scans->u]; diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index 0f4c65f13..60590c4d3 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -81,7 +81,7 @@ D_DrawSolidSurface (surf_t *surf, int color) pix = (color << 24) | (color << 16) | (color << 8) | color; for (span = surf->spans; span; span = span->pnext) { - pdest = d_viewbuffer + screenwidth * span->v; + pdest = d_viewbuffer + d_rowbytes * span->v; u = span->u; u2 = span->u + span->count - 1; ((byte *) pdest)[u] = pix; diff --git a/libs/video/renderer/sw/d_init.c b/libs/video/renderer/sw/d_init.c index 349733f76..ec0353817 100644 --- a/libs/video/renderer/sw/d_init.c +++ b/libs/video/renderer/sw/d_init.c @@ -45,6 +45,7 @@ float d_scalemip[NUM_MIPS - 1]; static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 }; +static byte *surfcache; void (*d_drawspans) (espan_t *pspan); @@ -60,29 +61,16 @@ D_Init (void) vid->vid_internal->flush_caches = D_FlushCaches; - int buffersize = vid->rowbytes * vid->height; - int zbuffersize = vid->width * vid->height * sizeof (*vid->zbuffer); int cachesize = D_SurfaceCacheForRes (vid->width, vid->height); - if (vid->zbuffer) { - free (vid->zbuffer); - vid->zbuffer = 0; + if (surfcache) { + D_FlushCaches (vid->vid_internal->data); + free (surfcache); + surfcache = 0; } - if (vid->surfcache) { - D_FlushCaches (0); - free (vid->surfcache); - vid->surfcache = 0; - } - if (vid->vid_internal->init_buffers) { - vid->vid_internal->init_buffers (vid->vid_internal->data); - } else { - free (vid->buffer); - vid->buffer = calloc (buffersize, 1); - } - vid->zbuffer = calloc (zbuffersize, 1); - vid->surfcache = calloc (cachesize, 1); - - D_InitCaches (vid->surfcache, cachesize); + surfcache = calloc (cachesize, 1); + vid->vid_internal->init_buffers (vid->vid_internal->data); + D_InitCaches (surfcache, cachesize); } void @@ -96,16 +84,6 @@ D_SetupFrame (void) { int i; - if (r_dowarp) - d_viewbuffer = r_warpbuffer; - else - d_viewbuffer = vid.buffer; - - if (r_dowarp) - screenwidth = WARP_WIDTH; - else - screenwidth = vid.rowbytes; - d_roverwrapped = false; d_initial_rover = sc_rover; diff --git a/libs/video/renderer/sw/d_modech.c b/libs/video/renderer/sw/d_modech.c index 3709cc179..0d17c2550 100644 --- a/libs/video/renderer/sw/d_modech.c +++ b/libs/video/renderer/sw/d_modech.c @@ -65,20 +65,10 @@ D_Patch (void) void D_ViewChanged (void) { - int rowpixels; - - if (r_dowarp) - rowpixels = WARP_WIDTH; - else - rowpixels = vid.rowbytes; - scale_for_mip = xscale; if (yscale > xscale) scale_for_mip = yscale; - d_zrowbytes = vid.width * 2; - d_zwidth = vid.width; - d_pix_min = r_refdef.vrect.width / 320; if (d_pix_min < 1) d_pix_min = 1; @@ -99,14 +89,5 @@ D_ViewChanged (void) d_vrectbottom_particle = r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift); - { - unsigned i; - - for (i = 0; i < vid.height; i++) { - d_scantable[i] = i * rowpixels; - zspantable[i] = d_zbuffer + i * d_zwidth; - } - } - D_Patch (); } diff --git a/libs/video/renderer/sw/d_part.c b/libs/video/renderer/sw/d_part.c index 65fa5ddac..f79229b9f 100644 --- a/libs/video/renderer/sw/d_part.c +++ b/libs/video/renderer/sw/d_part.c @@ -81,7 +81,7 @@ D_DrawParticle (particle_t *pparticle) switch (pix) { case 1: count = 1 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -91,7 +91,7 @@ D_DrawParticle (particle_t *pparticle) case 2: count = 2 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -106,7 +106,7 @@ D_DrawParticle (particle_t *pparticle) case 3: count = 3 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -126,7 +126,7 @@ D_DrawParticle (particle_t *pparticle) case 4: count = 4 << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { if (pz[0] <= izi) { pz[0] = izi; pdest[0] = pparticle->icolor; @@ -151,7 +151,7 @@ D_DrawParticle (particle_t *pparticle) default: count = pix << d_y_aspect_shift; - for (; count; count--, pz += d_zwidth, pdest += screenwidth) { + for (; count; count--, pz += d_zwidth, pdest += d_rowbytes) { for (i = 0; i < pix; i++) { if (pz[i] <= izi) { pz[i] = izi; diff --git a/libs/video/renderer/sw/d_parta.S b/libs/video/renderer/sw/d_parta.S index 41debaa27..ab4b8c969 100644 --- a/libs/video/renderer/sw/d_parta.S +++ b/libs/video/renderer/sw/d_parta.S @@ -245,7 +245,7 @@ C(DP_1x1): .globl C(DP_2x2) C(DP_2x2): pushl %esi - movl C(screenwidth),%ebx + movl C(d_rowbytes),%ebx movl C(d_zrowbytes),%esi cmpw %bp,(%edx) @@ -276,7 +276,7 @@ L2x2_4: .globl C(DP_3x3) C(DP_3x3): pushl %esi - movl C(screenwidth),%ebx + movl C(d_rowbytes),%ebx movl C(d_zrowbytes),%esi cmpw %bp,(%edx) @@ -335,7 +335,7 @@ L3x3_9: .globl C(DP_4x4) C(DP_4x4): pushl %esi - movl C(screenwidth),%ebx + movl C(d_rowbytes),%ebx movl C(d_zrowbytes),%esi cmpw %bp,(%edx) @@ -438,7 +438,7 @@ LDefault: movb C(d_y_aspect_shift),%cl shll %cl,%ebx -// for ( ; count ; count--, pz += d_zwidth, pdest += screenwidth) +// for ( ; count ; count--, pz += d_zwidth, pdest += d_rowbytes) // { // for (i=0 ; iframebuffer->buffer; int w, h; int u, v; int scr_x = vr_data.scr_view->xpos; @@ -59,6 +61,8 @@ D_WarpScreen (void) int *turb; int *col; byte **row; + byte *color = _swfb->color; + int rowbytes = _swfb->rowbytes; /* FIXME: allocate these arrays properly */ byte *rowptr[MAXHEIGHT + AMP2 * 2]; @@ -72,8 +76,8 @@ D_WarpScreen (void) hratio = h / (float) scr_h; for (v = 0; v < scr_h + AMP2 * 2; v++) { - rowptr[v] = d_viewbuffer + (r_refdef.vrect.y * screenwidth) + - (screenwidth * (int) ((float) v * hratio * h / (h + AMP2 * 2))); + rowptr[v] = d_viewbuffer + (0*r_refdef.vrect.y * d_rowbytes) + + (d_rowbytes * (int) ((float) v * hratio * h / (h + AMP2 * 2))); } for (u = 0; u < scr_w + AMP2 * 2; u++) { @@ -82,9 +86,9 @@ D_WarpScreen (void) } turb = intsintable + ((int) (vr_data.realtime * SPEED) & (CYCLE - 1)); - dest = ((byte*)vid.buffer) + scr_y * vid.rowbytes + scr_x; + dest = color + scr_y * rowbytes + scr_x; - for (v = 0; v < scr_h; v++, dest += vid.rowbytes) { + for (v = 0; v < scr_h; v++, dest += rowbytes) { col = &column[turb[v]]; row = &rowptr[v]; for (u = 0; u < scr_w; u += 4) { @@ -141,7 +145,7 @@ Turbulent (espan_t *pspan) zi16stepu = d_zistepu * 16; do { - r_turb_pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + r_turb_pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; count = pspan->count; @@ -265,7 +269,7 @@ D_DrawSpans8 (espan_t *pspan) zi8stepu = d_zistepu * 8; do { - pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index bfc3a2fed..2671de132 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -78,7 +78,7 @@ D_DrawSkyScans (espan_t *pspan) tnext = 0; // ditto do { - pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_spr8.S b/libs/video/renderer/sw/d_spr8.S index b2174b384..ebc005d9c 100644 --- a/libs/video/renderer/sw/d_spr8.S +++ b/libs/video/renderer/sw/d_spr8.S @@ -223,7 +223,7 @@ LSpanLoop: pushl %ebx // preserve spans pointer movl C(tadjust),%edx movl C(sadjust),%esi - movl C(d_scantable)(,%eax,4),%edi // v * screenwidth + movl C(d_scantable)(,%eax,4),%edi // v * d_rowbytes addl %ebp,%edi movl sspan_t_u(%ebx),%ebp addl %ebp,%edi // pdest = &pdestspan[scans->u]; diff --git a/libs/video/renderer/sw/d_sprite.c b/libs/video/renderer/sw/d_sprite.c index 884e2dbd7..c17e5957f 100644 --- a/libs/video/renderer/sw/d_sprite.c +++ b/libs/video/renderer/sw/d_sprite.c @@ -69,7 +69,7 @@ D_SpriteDrawSpans (sspan_t *pspan) izistep = (int) (d_zistepu * 0x8000 * 0x10000); do { - pdest = d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + pdest = d_viewbuffer + (d_rowbytes * pspan->v) + pspan->u; pz = d_zbuffer + (d_zwidth * pspan->v) + pspan->u; count = pspan->count; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 59c28c4cb..cc90bd95b 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -108,8 +108,6 @@ D_InitCaches (void *buffer, int size) sc_base->owner = NULL; sc_base->size = sc_size; - d_zbuffer = vid.zbuffer; - D_ClearCacheGuard (); } diff --git a/libs/video/renderer/sw/d_vars.c b/libs/video/renderer/sw/d_vars.c index 88288f8bb..5864d906b 100644 --- a/libs/video/renderer/sw/d_vars.c +++ b/libs/video/renderer/sw/d_vars.c @@ -54,7 +54,9 @@ byte *cacheblock; int cachewidth; byte *d_viewbuffer; short *d_zbuffer; +int d_rowbytes; int d_zrowbytes; int d_zwidth; +int d_height; #endif // !USE_INTEL_ASM diff --git a/libs/video/renderer/sw/d_varsa.S b/libs/video/renderer/sw/d_varsa.S index 642e7ab47..dba80a3e6 100644 --- a/libs/video/renderer/sw/d_varsa.S +++ b/libs/video/renderer/sw/d_varsa.S @@ -80,6 +80,8 @@ C(bbextentt): .long 0 .globl C(cacheblock) .globl C(d_viewbuffer) +.globl C(d_rowbytes) +.globl C(d_height) .globl C(cachewidth) .globl C(d_zbuffer) .globl C(d_zrowbytes) @@ -87,6 +89,8 @@ C(bbextentt): .long 0 C(cacheblock): .long 0 C(cachewidth): .long 0 C(d_viewbuffer): .long 0 +C(d_rowbytes): .long 0 +C(d_height): .long 0 C(d_zbuffer): .long 0 C(d_zrowbytes): .long 0 C(d_zwidth): .long 0 diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index c909dd293..750105e39 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -45,6 +45,7 @@ #include "QF/ui/view.h" #include "d_iface.h" +#include "d_local.h" #include "r_internal.h" #include "vid_internal.h" @@ -279,7 +280,7 @@ Draw_Character (int x, int y, unsigned int chr) } else drawline = 8; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; while (drawline--) { if (source[0]) @@ -299,7 +300,7 @@ Draw_Character (int x, int y, unsigned int chr) if (source[7]) dest[7] = source[7]; source += 128; - dest += vid.rowbytes; + dest += d_rowbytes; } } @@ -339,7 +340,7 @@ Draw_Pixel (int x, int y, byte color) { byte *dest; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; *dest = color; } @@ -493,7 +494,7 @@ Draw_Pic (int x, int y, qpic_t *pic) source = pic->data; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; if (pic->width & 7) { // general for (v = 0; v < pic->height; v++) { @@ -501,7 +502,7 @@ Draw_Pic (int x, int y, qpic_t *pic) if ((tbyte = source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } else { // unwound @@ -524,7 +525,7 @@ Draw_Pic (int x, int y, qpic_t *pic) if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) dest[u + 7] = tbyte; } - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } @@ -571,7 +572,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, source = pic->data + srcy * pic->width + srcx; - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; + dest = d_viewbuffer + y * d_rowbytes + x; if (width & 7) { // general for (v = 0; v < height; v++) { @@ -579,7 +580,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, if ((tbyte = source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } else { // unwound @@ -602,7 +603,7 @@ Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) dest[u + 7] = tbyte; } - dest += vid.rowbytes; + dest += d_rowbytes; source += pic->width; } } @@ -620,9 +621,9 @@ Draw_ConsoleBackground (int lines, byte alpha) conback = Draw_CachePic ("gfx/conback.lmp", false); // draw the pic - dest = vid.buffer; + dest = d_viewbuffer; - for (y = 0; y < lines; y++, dest += vid.rowbytes) { + for (y = 0; y < lines; y++, dest += d_rowbytes) { v = (vid.conview->ylen - lines + y) * 200 / vid.conview->ylen; src = conback->data + v * 320; if (vid.conview->xlen == 320) @@ -654,10 +655,10 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) int i, j, srcdelta, destdelta; byte *pdest; - pdest = ((byte*)vid.buffer) + (prect->y * vid.rowbytes) + prect->x; + pdest = d_viewbuffer + (prect->y * d_rowbytes) + prect->x; srcdelta = rowbytes - prect->width; - destdelta = vid.rowbytes - prect->width; + destdelta = d_rowbytes - prect->width; if (transparent) { for (i = 0; i < prect->height; i++) { @@ -678,7 +679,7 @@ R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) for (i = 0; i < prect->height; i++) { memcpy (pdest, psrc, prect->width); psrc += rowbytes; - pdest += vid.rowbytes; + pdest += d_rowbytes; } } } @@ -754,8 +755,8 @@ Draw_Fill (int x, int y, int w, int h, int c) } CLIP (x, y, w, h, (int) vid.width, (int) vid.height); - dest = ((byte*)vid.buffer) + y * vid.rowbytes + x; - for (v = 0; v < h; v++, dest += vid.rowbytes) + dest = d_viewbuffer + y * d_rowbytes + x; + for (v = 0; v < h; v++, dest += d_rowbytes) for (u = 0; u < w; u++) dest[u] = c; } @@ -774,7 +775,7 @@ Draw_FadeScreen (void) for (y = 0; y < height; y++) { uint32_t mask; - pbuf = (uint32_t *) ((byte *)vid.buffer + vid.rowbytes * y); + pbuf = (uint32_t *) (d_viewbuffer + d_rowbytes * y); mask = 0xff << ((y & 1) << 4); for (x = 0; x < width; x++) { diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 30a60379e..543d831f1 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -45,24 +45,27 @@ sw_SCR_CaptureBGR (void) tex_t *tex; const byte *src; byte *dst; + framebuffer_t *fb = sw_ctx->framebuffer; - count = vid.width * vid.height; + count = fb->width * fb->height; tex = malloc (sizeof (tex_t) + count * 3); tex->data = (byte *) (tex + 1); SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; + tex->width = fb->width; + tex->height = fb->height; tex->format = tex_rgb; tex->palette = 0; - src = vid.buffer; + src = ((sw_framebuffer_t *) fb->buffer)->color; + int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; for (y = 0; y < tex->height; y++) { dst = tex->data + (tex->height - 1 - y) * tex->width * 3; for (x = 0; x < tex->width; x++) { - *dst++ = vid.basepal[*src * 3 + 2]; // blue - *dst++ = vid.basepal[*src * 3 + 1]; // green - *dst++ = vid.basepal[*src * 3 + 0]; // red - src++; + byte c = src[x]; + *dst++ = vid.basepal[c * 3 + 2]; // blue + *dst++ = vid.basepal[c * 3 + 1]; // green + *dst++ = vid.basepal[c * 3 + 0]; // red } + src += rowbytes; } return tex; } diff --git a/libs/video/renderer/sw/sw_graph.c b/libs/video/renderer/sw/sw_graph.c index 4480a7eb7..da8d17a90 100644 --- a/libs/video/renderer/sw/sw_graph.c +++ b/libs/video/renderer/sw/sw_graph.c @@ -33,6 +33,7 @@ #include "QF/render.h" #include "r_internal.h" +#include "vid_sw.h" /* R_LineGraph @@ -44,12 +45,13 @@ R_LineGraph (int x, int y, int *h_vals, int count, int height) { int h, i, s, color; byte *dest; + sw_framebuffer_t *fb = sw_ctx->framebuffer->buffer; // FIXME: disable on no-buffer adapters, or put in the driver s = height; while (count--) { - dest = ((byte*)vid.buffer) + vid.rowbytes * y + x++; + dest = fb->color + fb->rowbytes * y + x++; h = *h_vals++; @@ -65,7 +67,7 @@ R_LineGraph (int x, int y, int *h_vals, int count, int height) if (h > s) h = s; - for (i = 0; i < h; i++, dest -= vid.rowbytes) { + for (i = 0; i < h; i++, dest -= fb->rowbytes) { dest[0] = color; } } diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index 0c9a3dee2..acf1b4101 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -29,6 +29,7 @@ #endif #include +#include #include "QF/image.h" #include "QF/render.h" diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index 99778f9bb..11c3cfe96 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -54,6 +54,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" #ifdef PIC # undef USE_INTEL_ASM //XXX asm pic hack @@ -70,7 +71,7 @@ float r_aliasuvscale = 1.0; int r_outofsurfaces; int r_outofedges; -qboolean r_dowarp, r_dowarpold, r_viewchanged; +qboolean r_viewchanged; int c_surf; int r_maxsurfsseen, r_maxedgesseen; @@ -78,8 +79,6 @@ static int r_cnumsurfs; static qboolean r_surfsonstack; int r_clipflags; -byte *r_warpbuffer; - static byte *r_stack_start; // screen size info @@ -689,16 +688,12 @@ R_EdgeDrawing (entqueue_t *queue) static void R_RenderView_ (void) { - byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; - if (r_norefresh->int_val) return; if (!r_refdef.worldmodel) { return; } - r_warpbuffer = warpbuffer; - R_SetupFrame (); // make FDIV fast. This reduces timing precision after we've been running for a @@ -711,9 +706,6 @@ R_RenderView_ (void) R_DrawViewModel (); - if (r_dowarp) - D_WarpScreen (); - if (r_aliasstats->int_val) R_PrintAliasStats (); @@ -739,7 +731,7 @@ R_RenderView (void) if ((intptr_t) (&dummy) & 3) Sys_Error ("Stack is missaligned"); - if ((intptr_t) (&r_warpbuffer) & 3) + if ((intptr_t) (&colormap) & 3) Sys_Error ("Globals are missaligned"); if (!scr_fisheye->int_val) R_RenderView_ (); @@ -765,7 +757,7 @@ R_InitTurb (void) #define BOX_LEFT 3 #define BOX_TOP 4 #define BOX_BOTTOM 5 - +#if 0 static mat4f_t box_rotations[] = { { { 1, 0, 0, 0}, // front { 0, 1, 0, 0}, @@ -792,7 +784,7 @@ static mat4f_t box_rotations[] = { { 1, 0, 0, 0}, { 0, 0, 0, 1} }, }; - +#endif static int sw_cube_map_size; static void @@ -848,7 +840,7 @@ fisheyelookuptable (byte **buf, int width, int height, byte *scrp, double fov) } } } - +#if 0 static void rendercopy (void *dest) { @@ -901,16 +893,18 @@ renderside (byte *bufs, int side) memcpy (r_refdef.camera, camera, sizeof (camera)); memcpy (r_refdef.camera_inverse, camera_inverse, sizeof (camera_inverse)); } - +#endif static void renderlookup (byte **offs, byte* bufs) { - byte *p = (byte*)vid.buffer; - unsigned x, y; - for (y = 0; y < vid.height; y++) { - for (x = 0; x < vid.width; x++, offs++) + framebuffer_t *fb = sw_ctx->framebuffer; + sw_framebuffer_t *swfb = fb->buffer; + byte *p = swfb->color; + unsigned x, y; + for (y = 0; y < fb->height; y++) { + for (x = 0; x < fb->width; x++, offs++) p[x] = **offs; - p += vid.rowbytes; + p += swfb->rowbytes; } } @@ -950,7 +944,7 @@ R_RenderViewFishEye (void) pviews = views; memset (scrbufs, 0, scrsize*6); } - +#if 0 switch (views) { case 6: renderside (scrbufs + scrsize * BOX_BEHIND, BOX_BEHIND); case 5: renderside (scrbufs + scrsize * BOX_BOTTOM, BOX_BOTTOM); @@ -959,6 +953,7 @@ R_RenderViewFishEye (void) case 2: renderside (scrbufs + scrsize * BOX_RIGHT, BOX_RIGHT); default: renderside (scrbufs + scrsize * BOX_FRONT, BOX_FRONT); } +#endif #if 0 memset (scrbufs + scrsize*0, 31, sw_cube_map_size); memset (scrbufs + scrsize*1, 31, sw_cube_map_size); diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index f7d41734f..47818af22 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -173,9 +173,6 @@ R_SetUpFrustumIndexes (void) void R_SetupFrame (void) { - vrect_t vrect; - float w, h; - numbtofpolys = 0; // build the transformation matrix for the given view angles @@ -185,62 +182,6 @@ R_SetupFrame (void) VectorCopy (r_refdef.frame.forward, vfwd); VectorCopy (r_refdef.frame.up, vup); - r_dowarpold = r_dowarp; - r_dowarp = r_waterwarp->int_val && (r_refdef.viewleaf->contents <= - CONTENTS_WATER); - - if (scr_fisheye->int_val) { - //FIXME this shouldn't be necessary, but warp doesn't work well in - //fisheye, aand allowing the non-warp code to mess with vrect messes - //things up for the cube map rendering. This whole frame setup path - //needs to be redesigned - r_dowarp = r_viewchanged = 0; - } - if ((r_dowarp != r_dowarpold) || r_viewchanged) { - if (r_dowarp) { - if ((vid.width <= WARP_WIDTH) - && (vid.height <= WARP_HEIGHT)) { - vrect.x = 0; - vrect.y = 0; - vrect.width = vid.width; - vrect.height = vid.height; - - R_SetVrect (&vrect, &r_refdef.vrect, vr_data.lineadj); - R_ViewChanged (); - } else { - w = vid.width; - h = vid.height; - - if (w > WARP_WIDTH) { - h *= (float) WARP_WIDTH / w; - w = WARP_WIDTH; - } - - if (h > WARP_HEIGHT) { - h = WARP_HEIGHT; - w *= (float) WARP_HEIGHT / h; - } - - vrect.x = 0; - vrect.y = 0; - vrect.width = (int) w; - vrect.height = (int) h; - - R_SetVrect (&vrect, &r_refdef.vrect, - (int) ((float) vr_data.lineadj * - (h / (float) vid.height))); - R_ViewChanged (); - } - } else { - r_refdef.vrect.x = vr_data.scr_view->xpos; - r_refdef.vrect.y = vr_data.scr_view->ypos; - r_refdef.vrect.width = vr_data.scr_view->xlen; - r_refdef.vrect.height = vr_data.scr_view->ylen; - R_ViewChanged (); - } - - r_viewchanged = false; - } // start off with just the four screen edge clip planes R_TransformFrustum (); diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 6651b97ca..4bcdcbc65 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -300,6 +300,17 @@ gl_end_frame (void) } } +static framebuffer_t * +gl_create_frame_buffer (int width, int height) +{ + Sys_Error ("not implemented"); +} + +static void +gl_bind_framebuffer (framebuffer_t *framebuffer) +{ +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -339,6 +350,10 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_draw_transparent, gl_set_2d, gl_end_frame, + + gl_create_frame_buffer, + gl_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 2913cd4f5..35eab3a20 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -244,6 +244,17 @@ glsl_end_frame (void) qfeglFlush (); } +static framebuffer_t * +glsl_create_frame_buffer (int width, int height) +{ + Sys_Error ("not implemented"); +} + +static void +glsl_bind_framebuffer (framebuffer_t *framebuffer) +{ +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -283,6 +294,10 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_draw_transparent, glsl_set_2d, glsl_end_frame, + + glsl_create_frame_buffer, + glsl_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 010133375..d78c1b825 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -28,6 +28,8 @@ # include "config.h" #endif +#include + #include "QF/cvar.h" #include "QF/plugin/general.h" @@ -35,6 +37,7 @@ #include "QF/ui/view.h" +#include "d_local.h" #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" @@ -108,6 +111,8 @@ sw_vid_render_shutdown (void) { } +static void sw_bind_framebuffer (framebuffer_t *framebuffer); + static void sw_begin_frame (void) { @@ -131,6 +136,8 @@ sw_begin_frame (void) r_numallocatededges, r_maxedgesseen); } + sw_bind_framebuffer (0); + // do 3D refresh drawing, and then update the screen if (vr_data.scr_fullupdate++ < vid.numpages) { vr_data.scr_copyeverything = 1; @@ -152,6 +159,10 @@ sw_draw_transparent (void) static void sw_set_2d (int scaled) { + if (!scaled && r_dowarp) { + D_WarpScreen (); + sw_bind_framebuffer (0); + } } static void @@ -187,6 +198,68 @@ sw_end_frame (void) sw_ctx->update (sw_ctx, &vrect); } +static framebuffer_t * +sw_create_frame_buffer (int width, int height) +{ + size_t pixels = width * height; + size_t size = sizeof (framebuffer_t); + size += sizeof (sw_framebuffer_t); + size += pixels; // color buffer + size += pixels * sizeof (short); // depth buffer + + framebuffer_t *fb = malloc (size); + fb->width = width; + fb->height = height; + __auto_type buffer = (sw_framebuffer_t *) &fb[1]; + fb->buffer = buffer; + buffer->color = (byte *) &buffer[1]; + buffer->depth = (short *) (buffer->color + pixels); + buffer->rowbytes = width; + return fb; +} + +static void +sw_bind_framebuffer (framebuffer_t *framebuffer) +{ + int changed = 0; + + if (!framebuffer) { + framebuffer = sw_ctx->framebuffer; + } + sw_framebuffer_t *fb = framebuffer->buffer; + + if (!fb->depth) { + fb->depth = malloc (framebuffer->width * framebuffer->height + * sizeof (short)); + } + + if (d_zbuffer != fb->depth + || d_zwidth != framebuffer->width || d_height != framebuffer->height) { + d_zwidth = framebuffer->width; + d_zrowbytes = d_zwidth * sizeof (short); + for (unsigned i = 0; i < framebuffer->height; i++) { + zspantable[i] = fb->depth + i * d_zwidth; + } + changed = 1; + } + if (d_rowbytes != fb->rowbytes || d_height != framebuffer->height) { + d_rowbytes = fb->rowbytes; + d_height = framebuffer->height; + for (unsigned i = 0; i < framebuffer->height; i++) { + d_scantable[i] = i * d_rowbytes; + } + changed = 1; + } + d_viewbuffer = fb->color; + d_zbuffer = fb->depth; + + if (changed) { + vrect_t r = { 0, 0, framebuffer->width, framebuffer->height }; + R_SetVrect (&r, &r_refdef.vrect, 0); + R_ViewChanged (); + } +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -226,6 +299,10 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_draw_transparent, sw_set_2d, sw_end_frame, + + sw_create_frame_buffer, + sw_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 352d24ae3..1990ce1ef 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -418,6 +418,17 @@ vulkan_end_frame (void) vulkan_ctx->curFrame %= vulkan_ctx->frames.size; } +static framebuffer_t * +vulkan_create_frame_buffer (int width, int height) +{ + Sys_Error ("not implemented"); +} + +static void +vulkan_bind_framebuffer (framebuffer_t *framebuffer) +{ +} + static int is_bgr (VkFormat format) { @@ -696,6 +707,10 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_draw_transparent, vulkan_set_2d, vulkan_end_frame, + + vulkan_create_frame_buffer, + vulkan_bind_framebuffer, + &model_funcs }; diff --git a/libs/video/targets/vid_win.c b/libs/video/targets/vid_win.c index 47e62ef29..08de11276 100644 --- a/libs/video/targets/vid_win.c +++ b/libs/video/targets/vid_win.c @@ -39,11 +39,14 @@ static vid_internal_t vid_internal; +#if 0 static byte backingbuf[48 * 24]; +#endif void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { +#if 0 int i, j, reps = 1, repshift = 0; vrect_t rect; @@ -72,12 +75,14 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) rect.next = NULL; win_sw_context->update (win_sw_context, &rect); +#endif } void D_EndDirectRect (int x, int y, int width, int height) { +#if 0 int i, j, reps = 1, repshift = 0; vrect_t rect; @@ -102,6 +107,7 @@ D_EndDirectRect (int x, int y, int width, int height) rect.next = NULL; win_sw_context->update (win_sw_context, &rect); +#endif } static void diff --git a/libs/video/targets/vid_win_sw.c b/libs/video/targets/vid_win_sw.c index 9ded596fb..2e8667c85 100644 --- a/libs/video/targets/vid_win_sw.c +++ b/libs/video/targets/vid_win_sw.c @@ -72,6 +72,9 @@ static ddCreateProc_t ddCreate; static int dd_window_width = 640; static int dd_window_height = 480; +static sw_framebuffer_t swfb; +static framebuffer_t fb = { .buffer = &swfb }; + static void DD_UpdateRects (int width, int height) { @@ -94,8 +97,10 @@ VID_CreateDDrawDriver (int width, int height) dd_window_width = width; dd_window_height = height; - viddef.buffer = malloc (width * height); - viddef.rowbytes = width; + fb.width = width; + fb.height = height; + swfb.color = malloc (width * height); + swfb.rowbytes = width; if (!(hInstDDraw = LoadLibrary ("ddraw.dll"))) { return; @@ -162,7 +167,7 @@ VID_CreateDDrawDriver (int width, int height) } static void -VID_CreateGDIDriver (int width, int height, const byte *palette, void **buffer, +VID_CreateGDIDriver (int width, int height, const byte *palette, byte **buffer, int *rowbytes) { // common bitmap definition @@ -235,10 +240,13 @@ void Win_UnloadAllDrivers (void) { // shut down ddraw - if (viddef.buffer) { - free (viddef.buffer); - *(int *)0xdb = 0; - viddef.buffer = 0; + if (swfb.color) { + free (swfb.color); + swfb.color = 0; + } + if (swfb.depth) { + free (swfb.depth); + swfb.depth = 0; } if (dd_Clipper) { @@ -303,13 +311,17 @@ Win_CreateDriver (void) Win_UnloadAllDrivers (); VID_CreateGDIDriver (viddef.width, viddef.height, viddef.palette, - &viddef.buffer, &viddef.rowbytes); + &swfb.color, &swfb.rowbytes); } } static void win_init_bufers (void *data) { + sw_ctx_t *ctx = data; + + ctx->framebuffer = &fb; + Win_UnloadAllDrivers (); Win_CreateDriver (); } @@ -372,13 +384,13 @@ dd_blit_rect (vrect_t *rect) // convert pitch to 32-bit addressable ddsd.lPitch >>= 2; - byte *src = viddef.buffer + rect->y * viddef.rowbytes + rect->x; + byte *src = swfb.color + rect->y * swfb.rowbytes + rect->x; unsigned *dst = ddsd.lpSurface; for (int y = rect->height; y-- > 0; ) { for (int x = rect->width; x-- > 0; ) { *dst++ = st2d_8to32table[*src++].value; } - src += viddef.rowbytes - rect->width; + src += swfb.rowbytes - rect->width; dst += ddsd.lPitch - rect->width; } diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c index ed0719720..7601d72d0 100644 --- a/libs/video/targets/vid_x11_sw.c +++ b/libs/video/targets/vid_x11_sw.c @@ -219,17 +219,18 @@ x11_set_palette (sw_ctx_t *ctx, const byte *palette) } static void -st2_fixup (XImage *framebuf, int x, int y, int width, int height) +st2_fixup (sw_ctx_t *ctx, XImage *framebuf, int x, int y, int width, int height) { int xi, yi; unsigned char *src; PIXEL16 *dest; + sw_framebuffer_t *fb = ctx->framebuffer->buffer; if (x < 0 || y < 0) return; for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width]; + src = &fb->color[yi * fb->rowbytes]; dest = (PIXEL16 *) &framebuf->data[yi * framebuf->bytes_per_line]; for (xi = x; xi < x + width; xi++) { dest[xi] = st2d_8to16table[src[xi]]; @@ -238,18 +239,19 @@ st2_fixup (XImage *framebuf, int x, int y, int width, int height) } static void -st3_fixup (XImage * framebuf, int x, int y, int width, int height) +st3_fixup (sw_ctx_t *ctx, XImage *framebuf, int x, int y, int width, int height) { int yi; unsigned char *src; PIXEL24 *dest; + sw_framebuffer_t *fb = ctx->framebuffer->buffer; register int count, n; if (x < 0 || y < 0) return; for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width + x]; + src = &fb->color[yi * fb->rowbytes + x]; dest = (PIXEL24 *) &framebuf->data[yi * framebuf->bytes_per_line + x]; // Duff's Device @@ -280,13 +282,13 @@ st3_fixup (XImage * framebuf, int x, int y, int width, int height) } static void -x11_put_image (vrect_t *rects) +x11_put_image (vrect_t *rect) { if (doShm) { if (!XShmPutImage (x_disp, x_win, x_gc, x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { + rect->x, rect->y, rect->x, rect->y, + rect->width, rect->height, True)) { Sys_Error ("VID_Update: XShmPutImage failed"); } oktodraw = false; @@ -296,8 +298,8 @@ x11_put_image (vrect_t *rects) current_framebuffer = !current_framebuffer; } else { if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { + rect->x, rect->y, rect->x, rect->y, + rect->width, rect->height)) { Sys_Error ("VID_Update: XPutImage failed"); } } @@ -309,33 +311,46 @@ x11_put_image (vrect_t *rects) static void x11_sw8_8_update (sw_ctx_t *ctx, vrect_t *rects) { - while (rects) { - switch (x_visinfo->depth) { - case 16: - st2_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - case 24: - st3_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - } - x11_put_image (rects); + vrect_t urect = *rects; + while (rects->next) { rects = rects->next; + int minx = min (VRect_MinX (&urect), VRect_MinX (rects)); + int miny = min (VRect_MinY (&urect), VRect_MinY (rects)); + int maxx = max (VRect_MaxX (&urect), VRect_MaxX (rects)); + int maxy = max (VRect_MaxY (&urect), VRect_MaxY (rects)); + urect.x = minx; + urect.y = miny; + urect.width = maxx - minx; + urect.height = maxy - miny; } + x11_put_image (&urect); XSync (x_disp, False); r_data->scr_fullupdate = 0; + + sw_framebuffer_t *fb = ctx->framebuffer->buffer; + fb->color = (byte *) x_framebuffer[current_framebuffer]->data; } static void x11_sw8_16_update (sw_ctx_t *ctx, vrect_t *rects) { - while (rects) { - st2_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - x11_put_image (rects); + vrect_t urect = *rects; + st2_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + while (rects->next) { rects = rects->next; + st2_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + int minx = min (VRect_MinX (&urect), VRect_MinX (rects)); + int miny = min (VRect_MinY (&urect), VRect_MinY (rects)); + int maxx = max (VRect_MaxX (&urect), VRect_MaxX (rects)); + int maxy = max (VRect_MaxY (&urect), VRect_MaxY (rects)); + urect.x = minx; + urect.y = miny; + urect.width = maxx - minx; + urect.height = maxy - miny; } + x11_put_image (&urect); XSync (x_disp, False); r_data->scr_fullupdate = 0; } @@ -343,12 +358,23 @@ x11_sw8_16_update (sw_ctx_t *ctx, vrect_t *rects) static void x11_sw8_24_update (sw_ctx_t *ctx, vrect_t *rects) { - while (rects) { - st3_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - x11_put_image (rects); + vrect_t urect = *rects; + st3_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + while (rects->next) { rects = rects->next; + st3_fixup (ctx, x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + int minx = min (VRect_MinX (&urect), VRect_MinX (rects)); + int miny = min (VRect_MinY (&urect), VRect_MinY (rects)); + int maxx = max (VRect_MaxX (&urect), VRect_MaxX (rects)); + int maxy = max (VRect_MaxY (&urect), VRect_MaxY (rects)); + urect.x = minx; + urect.y = miny; + urect.width = maxx - minx; + urect.height = maxy - miny; } + x11_put_image (&urect); XSync (x_disp, False); r_data->scr_fullupdate = 0; } @@ -592,9 +618,16 @@ ResetSharedFrameBuffers (void) } } +static sw_framebuffer_t swfb; +static framebuffer_t fb = { .buffer = &swfb }; + static void x11_init_buffers (void *data) { + sw_ctx_t *ctx = data; + + ctx->framebuffer = &fb; + if (doShm) ResetSharedFrameBuffers (); else @@ -602,15 +635,18 @@ x11_init_buffers (void *data) current_framebuffer = 0; - viddef.rowbytes = viddef.width; + fb.width = viddef.width; + fb.height = viddef.height; if (x_visinfo->depth != 8) { - if (viddef.buffer) - free (viddef.buffer); - viddef.buffer = calloc (viddef.rowbytes, viddef.height); - if (!viddef.buffer) + if (swfb.color) + free (swfb.color); + swfb.rowbytes = viddef.width; + swfb.color = calloc (swfb.rowbytes, viddef.height); + if (!swfb.color) Sys_Error ("Not enough memory for video mode"); } else { - viddef.buffer = x_framebuffer[current_framebuffer]->data; + swfb.rowbytes = x_framebuffer[current_framebuffer]->bytes_per_line; + swfb.color = (byte *) x_framebuffer[current_framebuffer]->data; } }