/*************************************************************************** * * * Project64-video - A Nintendo 64 gfx plugin. * * http://www.pj64-emu.com/ * * Copyright (C) 2017 Project64. All rights reserved. * * Copyright (C) 2003-2009 Sergey 'Gonetz' Lipski * * Copyright (C) 2002 Dave2001 * * * * License: * * GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * * version 2 of the License, or (at your option) any later version. * * * ****************************************************************************/ #include #include "Gfx_1.3.h" #include "FBtoScreen.h" #include "TexCache.h" #include static int SetupFBtoScreenCombiner(uint32_t texture_size, uint32_t opaque) { int tmu; if (voodoo.tmem_ptr[GR_TMU0] + texture_size < voodoo.tex_max_addr[0]) { tmu = GR_TMU0; gfxTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); gfxTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); } else { if (voodoo.tmem_ptr[GR_TMU1] + texture_size >= voodoo.tex_max_addr[1]) ClearCache(); tmu = GR_TMU1; gfxTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); gfxTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, FXFALSE, FXFALSE); } int filter = (rdp.filter_mode != 2) ? GR_TEXTUREFILTER_POINT_SAMPLED : GR_TEXTUREFILTER_BILINEAR; grTexFilterMode(tmu, filter, filter); grTexClampMode(tmu, GR_TEXTURECLAMP_CLAMP, GR_TEXTURECLAMP_CLAMP); // gfxConstantColorValue (0xFFFFFFFF); gfxColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, // GR_COMBINE_OTHER_CONSTANT, FXFALSE); gfxAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); if (opaque) { grAlphaTestFunction(GR_CMP_ALWAYS); grAlphaBlendFunction(GR_BLEND_ONE, GR_BLEND_ZERO, GR_BLEND_ONE, GR_BLEND_ZERO); } else { grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ZERO); } grDepthBufferFunction(GR_CMP_ALWAYS); grCullMode(GR_CULL_DISABLE); grDepthMask(FXFALSE); rdp.update |= UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; return tmu; } static void DrawRE2Video(FB_TO_SCREEN_INFO & fb_info, float scale) { float scale_y = (float)fb_info.width / rdp.vi_height; float height = g_scr_res_x / scale_y; float ul_x = 0.5f; float ul_y = (g_scr_res_y - height) / 2.0f; float lr_y = g_scr_res_y - ul_y - 1.0f; float lr_x = g_scr_res_x - 1.0f; float lr_u = (fb_info.width - 1)*scale; float lr_v = (fb_info.height - 1)*scale; VERTEX v[4] = { { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, { 0.5f, 0.5f, 0.5f, 0.5f } }, { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, { lr_u, 0.5f, lr_u, 0.5f } }, { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, { 0.5f, lr_v, 0.5f, lr_v } }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, { lr_u, lr_v, lr_u, lr_v } } }; grDrawTriangle(&v[0], &v[2], &v[1]); grDrawTriangle(&v[2], &v[3], &v[1]); } static void DrawRE2Video256(FB_TO_SCREEN_INFO & fb_info) { WriteTrace(TraceRDP, TraceDebug, "DrawRE2Video256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr); uint32_t * src = (uint32_t*)(gfx.RDRAM + fb_info.addr); GrTexInfo t_info; t_info.smallLodLog2 = GFX_LOD_LOG2_256; t_info.largeLodLog2 = GFX_LOD_LOG2_256; t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; uint16_t * tex = (uint16_t*)texture_buffer; uint16_t * dst = tex; uint32_t col; uint8_t r, g, b; fb_info.height = minval(256, fb_info.height); for (uint32_t h = 0; h < fb_info.height; h++) { for (uint32_t w = 0; w < 256; w++) { col = *(src++); r = (uint8_t)((col >> 24) & 0xFF); r = (uint8_t)((float)r / 255.0f * 31.0f); g = (uint8_t)((col >> 16) & 0xFF); g = (uint8_t)((float)g / 255.0f * 63.0f); b = (uint8_t)((col >> 8) & 0xFF); b = (uint8_t)((float)b / 255.0f * 31.0f); *(dst++) = (r << 11) | (g << 5) | b; } src += (fb_info.width - 256); } t_info.format = GFX_TEXFMT_RGB_565; t_info.data = tex; int tmu = SetupFBtoScreenCombiner(gfxTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque); grTexDownloadMipMap(tmu, voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexSource(tmu, voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, &t_info); DrawRE2Video(fb_info, 1.0f); } static void DrawFrameBufferToScreen256(FB_TO_SCREEN_INFO & fb_info) { if (g_settings->hacks(CSettings::hack_RE2)) { DrawRE2Video256(fb_info); return; } WriteTrace(TraceRDP, TraceDebug, "DrawFrameBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr); uint32_t width = fb_info.lr_x - fb_info.ul_x + 1; uint32_t height = fb_info.lr_y - fb_info.ul_y + 1; GrTexInfo t_info; uint8_t * image = gfx.RDRAM + fb_info.addr; uint32_t width256 = ((width - 1) >> 8) + 1; uint32_t height256 = ((height - 1) >> 8) + 1; t_info.smallLodLog2 = t_info.largeLodLog2 = GFX_LOD_LOG2_256; t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; t_info.format = GFX_TEXFMT_ARGB_1555; uint16_t * tex = (uint16_t*)texture_buffer; t_info.data = tex; uint32_t tex_size = gfxTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info); int tmu = SetupFBtoScreenCombiner(tex_size*width256*height256, fb_info.opaque); uint16_t * src = (uint16_t*)image; src += fb_info.ul_x + fb_info.ul_y * fb_info.width; uint32_t * src32 = (uint32_t*)image; src32 += fb_info.ul_x + fb_info.ul_y * fb_info.width; uint32_t w_tail = width % 256; uint32_t h_tail = height % 256; uint16_t c; uint32_t c32; uint32_t idx; uint32_t bound = BMASK + 1 - fb_info.addr; bound = fb_info.size == 2 ? bound >> 1 : bound >> 2; uint8_t r, g, b, a; uint32_t cur_width, cur_height, cur_tail; uint32_t tex_adr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu]; if ((voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu] + tex_size*width256*height256 > TEXMEM_2MB_EDGE)) { tex_adr = TEXMEM_2MB_EDGE; } for (uint32_t h = 0; h < height256; h++) { for (uint32_t w = 0; w < width256; w++) { cur_width = (256 * (w + 1) < width) ? 256 : w_tail; cur_height = (256 * (h + 1) < height) ? 256 : h_tail; cur_tail = 256 - cur_width; uint16_t * dst = tex; if (fb_info.size == 2) { for (uint32_t y = 0; y < cur_height; y++) { for (uint32_t x = 0; x < cur_width; x++) { idx = (x + 256 * w + (y + 256 * h)*fb_info.width) ^ 1; if (idx >= bound) break; c = src[idx]; *(dst++) = (c >> 1) | ((c & 1) << 15); } dst += cur_tail; } } else { for (uint32_t y = 0; y < cur_height; y++) { for (uint32_t x = 0; x < cur_width; x++) { idx = (x + 256 * w + (y + 256 * h)*fb_info.width); if (idx >= bound) break; c32 = src32[idx]; r = (uint8_t)((c32 >> 24) & 0xFF); r = (uint8_t)((float)r / 255.0f * 31.0f); g = (uint8_t)((c32 >> 16) & 0xFF); g = (uint8_t)((float)g / 255.0f * 63.0f); b = (uint8_t)((c32 >> 8) & 0xFF); b = (uint8_t)((float)b / 255.0f * 31.0f); a = (c32 & 0xFF) ? 1 : 0; *(dst++) = (a << 15) | (r << 10) | (g << 5) | b; } dst += cur_tail; } } grTexDownloadMipMap(tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexSource(tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info); tex_adr += tex_size; float ul_x = (float)(fb_info.ul_x + 256 * w); float ul_y = (float)(fb_info.ul_y + 256 * h); float lr_x = (ul_x + (float)(cur_width)) * rdp.scale_x; float lr_y = (ul_y + (float)(cur_height)) * rdp.scale_y; ul_x *= rdp.scale_x; ul_y *= rdp.scale_y; ul_x += rdp.offset_x; ul_y += rdp.offset_y; lr_x += rdp.offset_x; lr_y += rdp.offset_y; float lr_u = (float)(cur_width - 1); float lr_v = (float)(cur_height - 1); // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, { 0.5f, 0.5f, 0.5f, 0.5f } }, { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, { lr_u, 0.5f, lr_u, 0.5f } }, { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, { 0.5f, lr_v, 0.5f, lr_v } }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, { lr_u, lr_v, lr_u, lr_v } } }; grDrawTriangle(&v[0], &v[2], &v[1]); grDrawTriangle(&v[2], &v[3], &v[1]); } } } bool DrawFrameBufferToScreen(FB_TO_SCREEN_INFO & fb_info) { if (fb_info.width < 200 || fb_info.size < 2) return false; uint32_t width = fb_info.lr_x - fb_info.ul_x + 1; uint32_t height = fb_info.lr_y - fb_info.ul_y + 1; uint32_t max_size = minval(voodoo.max_tex_size, 512); if (width > (uint32_t)max_size || height > (uint32_t)max_size) { DrawFrameBufferToScreen256(fb_info); return true; } WriteTrace(TraceRDP, TraceDebug, "DrawFrameBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr); GrTexInfo t_info; uint8_t * image = gfx.RDRAM + fb_info.addr; uint32_t texwidth; float scale; if (width <= 256) { texwidth = 256; scale = 1.0f; t_info.smallLodLog2 = t_info.largeLodLog2 = GFX_LOD_LOG2_256; } else { texwidth = 512; scale = 0.5f; t_info.smallLodLog2 = t_info.largeLodLog2 = GFX_LOD_LOG2_512; } if (height <= (texwidth >> 1)) { t_info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1; } else { t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; } if (fb_info.size == 2) { uint16_t * tex = (uint16_t*)texture_buffer; uint16_t * dst = tex; uint16_t * src = (uint16_t*)image; src += fb_info.ul_x + fb_info.ul_y * fb_info.width; uint16_t c; uint32_t idx; const uint32_t bound = (BMASK + 1 - fb_info.addr) >> 1; bool empty = true; for (uint32_t y = 0; y < height; y++) { for (uint32_t x = 0; x < width; x++) { idx = (x + y*fb_info.width) ^ 1; if (idx >= bound) break; c = src[idx]; if (c) empty = false; *(dst++) = (c >> 1) | ((c & 1) << 15); } dst += texwidth - width; } if (empty) return false; t_info.format = GFX_TEXFMT_ARGB_1555; t_info.data = tex; } else { uint32_t * tex = (uint32_t*)texture_buffer; uint32_t * dst = tex; uint32_t * src = (uint32_t*)image; src += fb_info.ul_x + fb_info.ul_y * fb_info.width; uint32_t col; uint32_t idx; const uint32_t bound = (BMASK + 1 - fb_info.addr) >> 2; for (uint32_t y = 0; y < height; y++) { for (uint32_t x = 0; x < width; x++) { idx = x + y*fb_info.width; if (idx >= bound) break; col = src[idx]; *(dst++) = (col >> 8) | 0xFF000000; } dst += texwidth - width; } t_info.format = GFX_TEXFMT_ARGB_8888; t_info.data = tex; } int tmu = SetupFBtoScreenCombiner(gfxTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque); grTexDownloadMipMap(tmu, voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexSource(tmu, voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, &t_info); if (g_settings->hacks(CSettings::hack_RE2)) { DrawRE2Video(fb_info, scale); } else { float ul_x = fb_info.ul_x * rdp.scale_x + rdp.offset_x; float ul_y = fb_info.ul_y * rdp.scale_y + rdp.offset_y; float lr_x = fb_info.lr_x * rdp.scale_x + rdp.offset_x; float lr_y = fb_info.lr_y * rdp.scale_y + rdp.offset_y; float lr_u = (width - 1)*scale; float lr_v = (height - 1)*scale; // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, { 0.5f, 0.5f, 0.5f, 0.5f } }, { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, { lr_u, 0.5f, lr_u, 0.5f } }, { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, { 0.5f, lr_v, 0.5f, lr_v } }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, { lr_u, lr_v, lr_u, lr_v } } }; grDrawTriangle(&v[0], &v[2], &v[1]); grDrawTriangle(&v[2], &v[3], &v[1]); } return true; } static void DrawDepthBufferToScreen256(FB_TO_SCREEN_INFO & fb_info) { WriteTrace(TraceRDP, TraceDebug, "DrawDepthBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr); uint32_t width = fb_info.lr_x - fb_info.ul_x + 1; uint32_t height = fb_info.lr_y - fb_info.ul_y + 1; GrTexInfo t_info; uint8_t * image = gfx.RDRAM + fb_info.addr; uint32_t width256 = ((width - 1) >> 8) + 1; uint32_t height256 = ((height - 1) >> 8) + 1; t_info.smallLodLog2 = t_info.largeLodLog2 = GFX_LOD_LOG2_256; t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; t_info.format = GFX_TEXFMT_ALPHA_INTENSITY_88; uint16_t * tex = (uint16_t*)texture_buffer; t_info.data = tex; uint32_t tex_size = gfxTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info); int tmu = SetupFBtoScreenCombiner(tex_size*width256*height256, fb_info.opaque); gfxConstantColorValue(rdp.fog_color); gfxColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_CONSTANT, FXFALSE); uint16_t * src = (uint16_t*)image; src += fb_info.ul_x + fb_info.ul_y * fb_info.width; uint32_t w_tail = width % 256; uint32_t h_tail = height % 256; uint32_t cur_width, cur_height, cur_tail; uint32_t tex_adr = voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu]; if ((voodoo.tmem_ptr[tmu] < TEXMEM_2MB_EDGE) && (voodoo.tmem_ptr[tmu] + tex_size*width256*height256 > TEXMEM_2MB_EDGE)) { tex_adr = TEXMEM_2MB_EDGE; } for (uint32_t h = 0; h < height256; h++) { for (uint32_t w = 0; w < width256; w++) { cur_width = (256 * (w + 1) < width) ? 256 : w_tail; cur_height = (256 * (h + 1) < height) ? 256 : h_tail; cur_tail = 256 - cur_width; uint16_t * dst = tex; for (uint32_t y = 0; y < cur_height; y++) { for (uint32_t x = 0; x < cur_width; x++) { *(dst++) = rdp.pal_8[src[(x + 256 * w + (y + 256 * h)*fb_info.width) ^ 1] >> 8]; } dst += cur_tail; } grTexDownloadMipMap(tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexSource(tmu, tex_adr, GR_MIPMAPLEVELMASK_BOTH, &t_info); tex_adr += tex_size; float ul_x = (float)(fb_info.ul_x + 256 * w); float ul_y = (float)(fb_info.ul_y + 256 * h); float lr_x = (ul_x + (float)(cur_width)) * rdp.scale_x + rdp.offset_x; float lr_y = (ul_y + (float)(cur_height)) * rdp.scale_y + rdp.offset_y; ul_x = ul_x * rdp.scale_x + rdp.offset_x; ul_y = ul_y * rdp.scale_y + rdp.offset_y; float lr_u = (float)(cur_width - 1); float lr_v = (float)(cur_height - 1); // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, 0.5f, 0.5f, 0.5f, 0.5f, { 0.5f, 0.5f, 0.5f, 0.5f } }, { lr_x, ul_y, 1, 1, lr_u, 0.5f, lr_u, 0.5f, { lr_u, 0.5f, lr_u, 0.5f } }, { ul_x, lr_y, 1, 1, 0.5f, lr_v, 0.5f, lr_v, { 0.5f, lr_v, 0.5f, lr_v } }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, { lr_u, lr_v, lr_u, lr_v } } }; grDrawTriangle(&v[0], &v[2], &v[1]); grDrawTriangle(&v[2], &v[3], &v[1]); } } } static void DrawHiresDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info) { WriteTrace(TraceRDP, TraceDebug, "DrawHiresDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr); GrTexInfo t_info; float scale = 0.25f; GrLOD_t LOD = GFX_LOD_LOG2_1024; if (g_scr_res_x > 1024) { scale = 0.125f; LOD = GFX_LOD_LOG2_2048; } t_info.format = GFX_TEXFMT_ALPHA_INTENSITY_88; t_info.smallLodLog2 = t_info.largeLodLog2 = LOD; t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; gfxConstantColorValue(rdp.fog_color); gfxColorCombine(GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_LOCAL_CONSTANT, GR_COMBINE_OTHER_NONE, FXFALSE); gfxAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_TEXTURE, FXFALSE); grAlphaBlendFunction(GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ZERO); grDepthBufferFunction(GR_CMP_ALWAYS); grDepthMask(FXFALSE); grCullMode(GR_CULL_DISABLE); gfxTexCombine(GR_TMU1, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_NONE, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); gfxTexCombine(GR_TMU0, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, GR_COMBINE_FUNCTION_LOCAL, GR_COMBINE_FACTOR_NONE, FXFALSE, FXFALSE); // grAuxBufferExt( GR_BUFFER_AUXBUFFER ); grTexSource(rdp.texbufs[0].tmu, rdp.texbufs[0].begin, GR_MIPMAPLEVELMASK_BOTH, &(t_info)); float ul_x = (float)rdp.scissor.ul_x; float ul_y = (float)rdp.scissor.ul_y; float lr_x = (float)rdp.scissor.lr_x; float lr_y = (float)rdp.scissor.lr_y; float ul_u = (float)rdp.scissor.ul_x * scale; float ul_v = (float)rdp.scissor.ul_y * scale; float lr_u = (float)rdp.scissor.lr_x * scale; float lr_v = (float)rdp.scissor.lr_y * scale; // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, ul_u, ul_v, ul_u, ul_v, { ul_u, ul_v, ul_u, ul_v } }, { lr_x, ul_y, 1, 1, lr_u, ul_v, lr_u, ul_v, { lr_u, ul_v, lr_u, ul_v } }, { ul_x, lr_y, 1, 1, ul_u, lr_v, ul_u, lr_v, { ul_u, lr_v, ul_u, lr_v } }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, { lr_u, lr_v, lr_u, lr_v } } }; grDrawTriangle(&v[0], &v[2], &v[1]); grDrawTriangle(&v[2], &v[3], &v[1]); // grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT ); rdp.update |= UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE; } void DrawDepthBufferToScreen(FB_TO_SCREEN_INFO & fb_info) { uint32_t width = fb_info.lr_x - fb_info.ul_x + 1; uint32_t height = fb_info.lr_y - fb_info.ul_y + 1; if (width > (uint32_t)voodoo.max_tex_size || height > (uint32_t)voodoo.max_tex_size || width > 512) { DrawDepthBufferToScreen256(fb_info); return; } if (g_settings->fb_hwfbe_enabled() && !evoodoo) { DrawHiresDepthBufferToScreen(fb_info); return; } WriteTrace(TraceRDP, TraceDebug, "DrawDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx", fb_info.ul_x, fb_info.ul_y, fb_info.lr_x, fb_info.lr_y, fb_info.size, fb_info.addr); GrTexInfo t_info; uint8_t * image = gfx.RDRAM + fb_info.addr; uint32_t texwidth; float scale; if (width <= 256) { texwidth = 256; scale = 1.0f; t_info.smallLodLog2 = t_info.largeLodLog2 = GFX_LOD_LOG2_256; } else { texwidth = 512; scale = 0.5f; t_info.smallLodLog2 = t_info.largeLodLog2 = GFX_LOD_LOG2_512; } if (height <= (texwidth >> 1)) { t_info.aspectRatioLog2 = GR_ASPECT_LOG2_2x1; } else { t_info.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; } uint16_t * tex = (uint16_t*)texture_buffer; uint16_t * dst = tex; uint16_t * src = (uint16_t*)image; src += fb_info.ul_x + fb_info.ul_y * fb_info.width; for (uint32_t y = 0; y < height; y++) { for (uint32_t x = 0; x < width; x++) { *(dst++) = rdp.pal_8[src[(x + y*fb_info.width) ^ 1] >> 8]; } dst += texwidth - width; } t_info.format = GFX_TEXFMT_ALPHA_INTENSITY_88; t_info.data = tex; int tmu = SetupFBtoScreenCombiner(gfxTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, &t_info), fb_info.opaque); gfxConstantColorValue(rdp.fog_color); gfxColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER, GR_COMBINE_FACTOR_ONE, GR_COMBINE_LOCAL_NONE, GR_COMBINE_OTHER_CONSTANT, FXFALSE); grTexDownloadMipMap(tmu, voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, &t_info); grTexSource(tmu, voodoo.tex_min_addr[tmu] + voodoo.tmem_ptr[tmu], GR_MIPMAPLEVELMASK_BOTH, &t_info); float ul_x = fb_info.ul_x * rdp.scale_x + rdp.offset_x; float ul_y = fb_info.ul_y * rdp.scale_y + rdp.offset_y; float lr_x = fb_info.lr_x * rdp.scale_x + rdp.offset_x; float lr_y = fb_info.lr_y * rdp.scale_y + rdp.offset_y; float lr_u = (width - 1)*scale; float lr_v = (height - 1)*scale; float zero = scale*0.5f; // Make the vertices VERTEX v[4] = { { ul_x, ul_y, 1, 1, zero, zero, zero, zero, { zero, zero, zero, zero } }, { lr_x, ul_y, 1, 1, lr_u, zero, lr_u, zero, { lr_u, zero, lr_u, zero } }, { ul_x, lr_y, 1, 1, zero, lr_v, zero, lr_v, { zero, lr_v, zero, lr_v } }, { lr_x, lr_y, 1, 1, lr_u, lr_v, lr_u, lr_v, { lr_u, lr_v, lr_u, lr_v } } }; grDrawTriangle(&v[0], &v[2], &v[1]); grDrawTriangle(&v[2], &v[3], &v[1]); }