From 0c437492b424eb383235b06219eae2ca4852beb1 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 24 Mar 2022 12:22:27 +0900 Subject: [PATCH] [renderer] Move to using dynamic frame buffers For now, OpenGL and Vulkan renderers are broken as I focused on getting the software renderer working (which was quite tricky to get right). This fixes a couple of issues: the segfault when warping the screen (due to the scene rendering move invalidating the warp buffer), and warp always having 320x200 resolution. There's still the problem of the effect being too subtle at high resolution, but that's just a matter of updating the tables and tweaking the code in D_WarpScreen. Another issue is the Draw functions should probably write directly to the main frame buffer or even one passed in as a parameter. This would remove the need for binding the main buffer at the beginning and end of the frame. --- include/QF/plugin/vid_render.h | 3 + include/QF/render.h | 10 +++ include/QF/scene/camera.h | 1 + include/QF/vid.h | 4 - include/d_iface.h | 2 - include/d_local.h | 9 +- include/quakeasm.h | 2 +- include/r_local.h | 2 - include/r_shared.h | 1 - include/vid_gl.h | 6 ++ include/vid_sw.h | 9 ++ libs/video/renderer/r_main.c | 1 + libs/video/renderer/r_screen.c | 11 +++ libs/video/renderer/sw/d_draw.S | 2 +- libs/video/renderer/sw/d_edge.c | 2 +- libs/video/renderer/sw/d_init.c | 38 ++------- libs/video/renderer/sw/d_modech.c | 19 ----- libs/video/renderer/sw/d_part.c | 10 +-- libs/video/renderer/sw/d_parta.S | 10 +-- libs/video/renderer/sw/d_polyse.c | 8 +- libs/video/renderer/sw/d_scan.c | 16 ++-- libs/video/renderer/sw/d_sky.c | 2 +- libs/video/renderer/sw/d_spr8.S | 2 +- libs/video/renderer/sw/d_sprite.c | 2 +- libs/video/renderer/sw/d_surf.c | 2 - libs/video/renderer/sw/d_vars.c | 2 + libs/video/renderer/sw/d_varsa.S | 4 + libs/video/renderer/sw/draw.c | 35 ++++---- libs/video/renderer/sw/screen.c | 19 +++-- libs/video/renderer/sw/sw_graph.c | 6 +- libs/video/renderer/sw/sw_ralias.c | 1 + libs/video/renderer/sw/sw_rmain.c | 37 ++++----- libs/video/renderer/sw/sw_rmisc.c | 59 ------------- libs/video/renderer/vid_render_gl.c | 15 ++++ libs/video/renderer/vid_render_glsl.c | 15 ++++ libs/video/renderer/vid_render_sw.c | 77 +++++++++++++++++ libs/video/renderer/vid_render_vulkan.c | 15 ++++ libs/video/targets/vid_win.c | 6 ++ libs/video/targets/vid_win_sw.c | 32 ++++--- libs/video/targets/vid_x11_sw.c | 106 ++++++++++++++++-------- 40 files changed, 362 insertions(+), 241 deletions(-) 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; } }