diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 6e47116e589..cf7638605eb 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -6229,6 +6229,7 @@ struct arbfp_blit_priv { GLenum yuy2_rect_shader, yuy2_2d_shader; GLenum uyvy_rect_shader, uyvy_2d_shader; GLenum yv12_rect_shader, yv12_2d_shader; + GLenum p8_rect_shader, p8_2d_shader; }; static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) { @@ -6253,7 +6254,9 @@ static void arbfp_blit_free(IWineD3DDevice *iface) { GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_2d_shader)); GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_rect_shader)); GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_2d_shader)); - checkGLcall("Delete yuv programs"); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_rect_shader)); + GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_2d_shader)); + checkGLcall("Delete yuv and p8 programs"); LEAVE_GL(); HeapFree(GetProcessHeap(), 0, device->blit_priv); @@ -6494,6 +6497,72 @@ static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, return TRUE; } +static GLuint gen_p8_shader(IWineD3DDeviceImpl *device, GLenum textype) +{ + GLenum shader; + struct wined3d_shader_buffer buffer; + struct arbfp_blit_priv *priv = device->blit_priv; + GLint pos; + + /* Shader header */ + if (!shader_buffer_init(&buffer)) + { + ERR("Failed to initialize shader buffer.\n"); + return 0; + } + + ENTER_GL(); + GL_EXTCALL(glGenProgramsARB(1, &shader)); + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)); + LEAVE_GL(); + if(!shader) { + shader_buffer_free(&buffer); + return 0; + } + + shader_addline(&buffer, "!!ARBfp1.0\n"); + shader_addline(&buffer, "TEMP index;\n"); + + /* { 255/256, 0.5/255*255/256, 0, 0 } */ + shader_addline(&buffer, "PARAM constants = { 0.996, 0.00195, 0, 0 };\n"); + + /* The alpha-component contains the palette index */ + if(textype == GL_TEXTURE_RECTANGLE_ARB) + shader_addline(&buffer, "TXP index, fragment.texcoord[0], texture[0], RECT;\n"); + else + shader_addline(&buffer, "TEX index, fragment.texcoord[0], texture[0], 2D;\n"); + + /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */ + shader_addline(&buffer, "MAD index.a, index.a, constants.x, constants.y;\n"); + + /* Use the alpha-component as an index in the palette to get the final color */ + shader_addline(&buffer, "TEX result.color, index.a, texture[1], 1D;\n"); + shader_addline(&buffer, "END\n"); + + ENTER_GL(); + GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, + strlen(buffer.buffer), buffer.buffer)); + checkGLcall("glProgramStringARB()"); + + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos); + if (pos != -1) + { + FIXME("Fragment program error at position %d: %s\n\n", pos, + debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB))); + shader_arb_dump_program_source(buffer.buffer); + } + + if (textype == GL_TEXTURE_RECTANGLE_ARB) + priv->p8_rect_shader = shader; + else + priv->p8_2d_shader = shader; + + shader_buffer_free(&buffer); + LEAVE_GL(); + + return shader; +} + /* Context activation is done by the caller. */ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum complex_fixup yuv_fixup, GLenum textype) { @@ -6643,6 +6712,8 @@ static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum complex_fixup yuv_ if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yv12_rect_shader = shader; else priv->yv12_2d_shader = shader; break; + default: + ERR("Unsupported complex fixup: %d\n", yuv_fixup); } return shader; @@ -6686,8 +6757,13 @@ static HRESULT arbfp_blit_set(IWineD3DDevice *iface, const struct GlPixelFormatD shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yv12_rect_shader : priv->yv12_2d_shader; break; + case COMPLEX_FIXUP_P8: + shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->p8_rect_shader : priv->p8_2d_shader; + if (!shader) shader = gen_p8_shader(device, textype); + break; + default: - FIXME("Unsupported YUV fixup %#x, not setting a shader\n", fixup); + FIXME("Unsupported complex fixup %#x, not setting a shader\n", fixup); ENTER_GL(); glEnable(textype); checkGLcall("glEnable(textype)"); @@ -6761,6 +6837,7 @@ static BOOL arbfp_blit_color_fixup_supported(struct color_fixup_desc fixup) case COMPLEX_FIXUP_YUY2: case COMPLEX_FIXUP_UYVY: case COMPLEX_FIXUP_YV12: + case COMPLEX_FIXUP_P8: TRACE("[OK]\n"); return TRUE; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 578d8e4808b..6682aa4635e 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1720,14 +1720,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, } } - /* Delete the palette conversion shader if it is around */ - if(This->paletteConversionShader) { - ENTER_GL(); - GL_EXTCALL(glDeleteProgramsARB(1, &This->paletteConversionShader)); - LEAVE_GL(); - This->paletteConversionShader = 0; - } - /* Delete the pbuffer context if there is any */ if(This->pbufferContext) context_destroy(This, This->pbufferContext); diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c index d5d2246bc4e..d17d35cc16d 100644 --- a/dlls/wined3d/surface.c +++ b/dlls/wined3d/surface.c @@ -1853,7 +1853,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ * in which the main render target uses p8. Some games like GTA Vice City use P8 for texturing which * conflicts with this. */ - if (!(gl_info->supported[EXT_PALETTED_TEXTURE] || (gl_info->supported[ARB_FRAGMENT_PROGRAM] + if (!(gl_info->supported[EXT_PALETTED_TEXTURE] || (device->blitter->color_fixup_supported(This->resource.format_desc->color_fixup) && device->render_targets && This == (IWineD3DSurfaceImpl*)device->render_targets[0])) || colorkey_active || !use_texturing) { @@ -1867,7 +1867,7 @@ HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_ *convert = CONVERT_PALETTED; } } - else if (!gl_info->supported[EXT_PALETTED_TEXTURE] && gl_info->supported[ARB_FRAGMENT_PROGRAM]) + else if (!gl_info->supported[EXT_PALETTED_TEXTURE] && device->blitter->color_fixup_supported(This->resource.format_desc->color_fixup)) { *format = GL_ALPHA; *type = GL_UNSIGNED_BYTE; @@ -2584,34 +2584,10 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve * The 8bit pixel data will be used as an index in this palette texture to retrieve the final color. */ TRACE("Using fragment shaders for emulating 8-bit paletted texture support\n"); + device->blitter->set_shader((IWineD3DDevice *) device, This->resource.format_desc, + This->texture_target, This->pow2Width, This->pow2Height); + ENTER_GL(); - - /* Create the fragment program if we don't have it */ - if(!device->paletteConversionShader) - { - const char *fragment_palette_conversion = - "!!ARBfp1.0\n" - "TEMP index;\n" - /* { 255/256, 0.5/255*255/256, 0, 0 } */ - "PARAM constants = { 0.996, 0.00195, 0, 0 };\n" - /* The alpha-component contains the palette index */ - "TEX index, fragment.texcoord[0], texture[0], 2D;\n" - /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */ - "MAD index.a, index.a, constants.x, constants.y;\n" - /* Use the alpha-component as an index in the palette to get the final color */ - "TEX result.color, index.a, texture[1], 1D;\n" - "END"; - - glEnable(GL_FRAGMENT_PROGRAM_ARB); - GL_EXTCALL(glGenProgramsARB(1, &device->paletteConversionShader)); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader)); - GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragment_palette_conversion), fragment_palette_conversion)); - glDisable(GL_FRAGMENT_PROGRAM_ARB); - } - - glEnable(GL_FRAGMENT_PROGRAM_ARB); - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader)); - GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1)); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); @@ -2625,7 +2601,6 @@ static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES conve /* Rebind the texture because it isn't bound anymore */ glBindTexture(This->texture_target, This->texture_name); - LEAVE_GL(); } } @@ -5065,7 +5040,7 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, D d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This); } else if (This->resource.format_desc->format == WINED3DFMT_P8_UINT - && (gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM])) + && (gl_info->supported[EXT_PALETTED_TEXTURE] || device->blitter->color_fixup_supported(This->resource.format_desc->color_fixup))) { d3dfmt_p8_upload_palette(iface, convert); mem = This->resource.allocatedMemory; diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 1cef5e98bf7..665f27fe980 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -1098,6 +1098,9 @@ static void apply_format_fixups(struct wined3d_gl_info *gl_info) gl_info->gl_formats[idx].heightscale = 1.5f; gl_info->gl_formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12); + idx = getFmtIdx(WINED3DFMT_P8_UINT); + gl_info->gl_formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8); + if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA]) { idx = getFmtIdx(WINED3DFMT_B8G8R8A8_UNORM); @@ -1930,6 +1933,7 @@ static const char *debug_complex_fixup(enum complex_fixup fixup) WINED3D_TO_STR(COMPLEX_FIXUP_YUY2); WINED3D_TO_STR(COMPLEX_FIXUP_UYVY); WINED3D_TO_STR(COMPLEX_FIXUP_YV12); + WINED3D_TO_STR(COMPLEX_FIXUP_P8); #undef WINED3D_TO_STR default: FIXME("Unrecognized complex fixup %#x\n", fixup); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 25cd004bd7d..20417df9ac8 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -70,6 +70,7 @@ enum complex_fixup COMPLEX_FIXUP_YUY2 = 0, COMPLEX_FIXUP_UYVY = 1, COMPLEX_FIXUP_YV12 = 2, + COMPLEX_FIXUP_P8 = 3, }; #include @@ -1644,7 +1645,6 @@ struct IWineD3DDeviceImpl UINT NumberOfPalettes; PALETTEENTRY **palettes; UINT currentPalette; - UINT paletteConversionShader; /* For rendering to a texture using glCopyTexImage */ GLenum *draw_buffers;