From e5e91e484f657a35d41e788b077815c324af9dd6 Mon Sep 17 00:00:00 2001 From: mpi Date: Wed, 29 Jul 2015 05:47:25 +0000 Subject: [PATCH] Make the Gallium r300 works on big-endian architectures. Diff provided by Michel Daenzer [0] as a possible solution for a regression introduced in Mesa 9 [1]. This diff allows macppc users to use OpenGL accelerated appplications (i.e. GNOME3). As disucssed during c2k15 we won't try to keep this patch during the next Mesa update. [0] https://bugs.freedesktop.org/show_bug.cgi?id=71789 [1] http://lists.freedesktop.org/archives/mesa-dev/2013-December/050218.html Tested by myself and ajacoutot@, regression test and ok jsg@ --- .../Mesa/src/gallium/drivers/r300/r300_blit.c | 4 +- .../src/gallium/drivers/r300/r300_context.h | 2 + .../src/gallium/drivers/r300/r300_state.c | 20 ++++++--- .../gallium/drivers/r300/r300_state_derived.c | 15 ++++--- .../src/gallium/drivers/r300/r300_texture.c | 44 +++++++++++++++++-- .../src/gallium/drivers/r300/r300_texture.h | 3 ++ .../src/gallium/drivers/r300/r300_transfer.c | 6 ++- .../state_trackers/dri/common/dri_drawable.c | 8 ++-- .../src/gallium/state_trackers/dri/drm/dri2.c | 20 ++++----- 9 files changed, 91 insertions(+), 31 deletions(-) diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_blit.c b/dist/Mesa/src/gallium/drivers/r300/r300_blit.c index 2b516d284..ea242e6ce 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_blit.c +++ b/dist/Mesa/src/gallium/drivers/r300/r300_blit.c @@ -185,7 +185,9 @@ static void r300_set_clear_color(struct r300_context *r300, union util_color uc; memset(&uc, 0, sizeof(uc)); - util_pack_color(color->f, fb->cbufs[0]->format, &uc); + util_pack_color(color->f, + r300_get_hw_format(fb->cbufs[0]->format, PIPE_BIND_RENDER_TARGET), + &uc); if (fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16A16_FLOAT || fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16X16_FLOAT) { diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_context.h b/dist/Mesa/src/gallium/drivers/r300/r300_context.h index 8736cc734..a05fac669 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_context.h +++ b/dist/Mesa/src/gallium/drivers/r300/r300_context.h @@ -45,6 +45,8 @@ struct r300_vertex_shader; struct r300_stencilref_context; enum colormask_swizzle { + COLORMASK_ARGB, + COLORMASK_XRGB, COLORMASK_BGRA, COLORMASK_RGBA, COLORMASK_RRRR, diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_state.c b/dist/Mesa/src/gallium/drivers/r300/r300_state.c index 7d83576cf..1ad12777c 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_state.c +++ b/dist/Mesa/src/gallium/drivers/r300/r300_state.c @@ -225,6 +225,12 @@ static unsigned blend_discard_conditionally(unsigned eqRGB, unsigned eqA, /* The hardware colormask is clunky a must be swizzled depending on the format. * This was figured out by trial-and-error. */ +static unsigned argb_cmask(unsigned mask) +{ + return ((mask & (PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B)) << 1) | + ((mask & PIPE_MASK_A) >> 3); +} + static unsigned bgra_cmask(unsigned mask) { return ((mask & PIPE_MASK_R) << 2) | @@ -471,6 +477,8 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* Build a command buffer. */ { unsigned (*func[COLORMASK_NUM_SWIZZLES])(unsigned) = { + argb_cmask, + argb_cmask, bgra_cmask, rgba_cmask, rrrr_cmask, @@ -482,7 +490,8 @@ static void* r300_create_blend_state(struct pipe_context* pipe, }; for (i = 0; i < COLORMASK_NUM_SWIZZLES; i++) { - boolean has_alpha = i != COLORMASK_RGBX && i != COLORMASK_BGRX; + boolean has_alpha = i != COLORMASK_RGBX && i != COLORMASK_BGRX && + i != COLORMASK_XRGB; BEGIN_CB(blend->cb_clamp[i], 8); OUT_CB_REG(R300_RB3D_ROPCNTL, rop); @@ -1667,6 +1676,7 @@ r300_create_sampler_view_custom(struct pipe_context *pipe, boolean dxtc_swizzle = r300_screen(pipe->screen)->caps.dxtc_swizzle; if (view) { + enum pipe_format format = r300_get_hw_format(templ->format, texture->bind); unsigned hwformat; view->base = *templ; @@ -1682,24 +1692,24 @@ r300_create_sampler_view_custom(struct pipe_context *pipe, view->swizzle[2] = templ->swizzle_b; view->swizzle[3] = templ->swizzle_a; - hwformat = r300_translate_texformat(templ->format, + hwformat = r300_translate_texformat(format, view->swizzle, is_r500, dxtc_swizzle); if (hwformat == ~0) { fprintf(stderr, "r300: Ooops. Got unsupported format %s in %s.\n", - util_format_short_name(templ->format), __func__); + util_format_short_name(format), __func__); } assert(hwformat != ~0); r300_texture_setup_format_state(r300_screen(pipe->screen), tex, - templ->format, 0, + format, 0, width0_override, height0_override, &view->format); view->format.format1 |= hwformat; if (is_r500) { - view->format.format2 |= r500_tx_format_msb_bit(templ->format); + view->format.format2 |= r500_tx_format_msb_bit(format); } } diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_state_derived.c b/dist/Mesa/src/gallium/drivers/r300/r300_state_derived.c index da472f4d7..8e638b743 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_state_derived.c +++ b/dist/Mesa/src/gallium/drivers/r300/r300_state_derived.c @@ -815,9 +815,12 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) for (i = 0; i < count; i++) { if (state->sampler_views[i] && state->sampler_states[i]) { + enum pipe_format format; + state->tx_enable |= 1 << i; view = state->sampler_views[i]; + format = r300_get_hw_format(view->base.format, view->base.texture->bind); tex = r300_resource(view->base.texture); sampler = state->sampler_states[i]; @@ -828,7 +831,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) /* Set the border color. */ texstate->border_color = - r300_get_border_color(view->base.format, + r300_get_border_color(format, sampler->state.border_color.f, r300->screen->caps.is_r500); @@ -852,7 +855,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) offset = tex->tex.offset_in_bytes[base_level]; r300_texture_setup_format_state(r300->screen, tex, - view->base.format, + format, base_level, view->width0_override, view->height0_override, @@ -865,11 +868,11 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) texstate->format.format1 |= view->texcache_region; /* Depth textures are kinda special. */ - if (util_format_is_depth_or_stencil(view->base.format)) { + if (util_format_is_depth_or_stencil(format)) { unsigned char depth_swizzle[4]; if (!r300->screen->caps.is_r500 && - util_format_get_blocksizebits(view->base.format) == 32) { + util_format_get_blocksizebits(format) == 32) { /* X24x8 is sampled as Y16X16 on r3xx-r4xx. * The depth here is at the Y component. */ for (j = 0; j < 4; j++) @@ -894,7 +897,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } if (r300->screen->caps.dxtc_swizzle && - util_format_is_compressed(view->base.format)) { + util_format_is_compressed(format)) { texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE; } @@ -940,7 +943,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } /* Float textures only support nearest and mip-nearest filtering. */ - if (util_format_is_float(view->base.format)) { + if (util_format_is_float(format)) { /* No MAG linear filtering. */ if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) == R300_TX_MAG_FILTER_LINEAR) { diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_texture.c b/dist/Mesa/src/gallium/drivers/r300/r300_texture.c index 4ea69dcb4..3a6432b4b 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_texture.c +++ b/dist/Mesa/src/gallium/drivers/r300/r300_texture.c @@ -90,6 +90,25 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, return result; } + +enum pipe_format r300_get_hw_format(enum pipe_format api_format, + unsigned bind) +{ + if (bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED) && + !(bind & (PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE))) { + switch (api_format) { + case PIPE_FORMAT_A8R8G8B8_UNORM: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case PIPE_FORMAT_X8R8G8B8_UNORM: + return PIPE_FORMAT_B8G8R8X8_UNORM; + default: + break; + } + } + + return api_format; +} + /* Translate a pipe_format into a useful texture format for sampling. * * Some special formats are translated directly using R300_EASY_TX_FORMAT, @@ -444,10 +463,14 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) return R300_COLOR_FORMAT_ARGB4444; /* 32-bit buffers. */ + case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ case PIPE_FORMAT_B8G8R8A8_UNORM: /*case PIPE_FORMAT_B8G8R8A8_SNORM:*/ case PIPE_FORMAT_B8G8R8X8_UNORM: /*case PIPE_FORMAT_B8G8R8X8_SNORM:*/ + case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8G8B8X8_UNORM: @@ -667,6 +690,10 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) R300_C2_SEL_R | R300_C3_SEL_A; /* ARGB outputs. */ + case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ + case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ case PIPE_FORMAT_A16_UNORM: case PIPE_FORMAT_A16_SNORM: case PIPE_FORMAT_A16_FLOAT: @@ -770,6 +797,14 @@ static uint32_t r300_translate_colormask_swizzle(enum pipe_format format) case PIPE_FORMAT_R32G32_FLOAT: return COLORMASK_GRRG; + case PIPE_FORMAT_A8R8G8B8_UNORM: + /*case PIPE_FORMAT_A8R8G8B8_SNORM:*/ + return COLORMASK_ARGB; + + case PIPE_FORMAT_X8R8G8B8_UNORM: + /*case PIPE_FORMAT_X8R8G8B8_SNORM:*/ + return COLORMASK_XRGB; + case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B4G4R4X4_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: @@ -936,14 +971,17 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf) surf->pitch_zmask = tex->tex.zmask_stride_in_pixels[level]; surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level]; } else { + enum pipe_format hwformat = r300_get_hw_format(surf->base.format, + surf->base.texture->bind); + surf->pitch = stride | - r300_translate_colorformat(surf->base.format) | + r300_translate_colorformat(hwformat) | R300_COLOR_TILE(tex->tex.macrotile[level]) | R300_COLOR_MICROTILE(tex->tex.microtile); - surf->format = r300_translate_out_fmt(surf->base.format); + surf->format = r300_translate_out_fmt(hwformat); surf->colormask_swizzle = - r300_translate_colormask_swizzle(surf->base.format); + r300_translate_colormask_swizzle(hwformat); surf->pitch_cmask = tex->tex.cmask_stride_in_pixels; } } diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_texture.h b/dist/Mesa/src/gallium/drivers/r300/r300_texture.h index 213bdffc2..d43bf6bed 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_texture.h +++ b/dist/Mesa/src/gallium/drivers/r300/r300_texture.h @@ -39,6 +39,9 @@ unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format, const unsigned char *swizzle_view, boolean dxtc_swizzle); +enum pipe_format r300_get_hw_format(enum pipe_format api_format, + unsigned bind); + uint32_t r300_translate_texformat(enum pipe_format format, const unsigned char *swizzle_view, boolean is_r500, diff --git a/dist/Mesa/src/gallium/drivers/r300/r300_transfer.c b/dist/Mesa/src/gallium/drivers/r300/r300_transfer.c index b87164ba8..7690da925 100644 --- a/dist/Mesa/src/gallium/drivers/r300/r300_transfer.c +++ b/dist/Mesa/src/gallium/drivers/r300/r300_transfer.c @@ -22,6 +22,7 @@ * USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "r300_transfer.h" +#include "r300_texture.h" #include "r300_texture_desc.h" #include "r300_screen_buffer.h" @@ -110,8 +111,8 @@ r300_texture_transfer_map(struct pipe_context *ctx, struct r300_context *r300 = r300_context(ctx); struct r300_resource *tex = r300_resource(texture); struct r300_transfer *trans; + enum pipe_format format = texture->format; boolean referenced_cs, referenced_hw; - enum pipe_format format = tex->b.b.format; char *map; referenced_cs = @@ -135,8 +136,9 @@ r300_texture_transfer_map(struct pipe_context *ctx, * for this transfer. * Also make write transfers pipelined. */ if (tex->tex.microtile || tex->tex.macrotile[level] || + r300_get_hw_format(format, texture->bind) != format || (referenced_hw && !(usage & PIPE_TRANSFER_READ) && - r300_is_blit_supported(texture->format))) { + r300_is_blit_supported(format))) { struct pipe_resource base; if (r300->blitter->running) { diff --git a/dist/Mesa/src/gallium/state_trackers/dri/common/dri_drawable.c b/dist/Mesa/src/gallium/state_trackers/dri/common/dri_drawable.c index b7df05359..def393a2b 100644 --- a/dist/Mesa/src/gallium/state_trackers/dri/common/dri_drawable.c +++ b/dist/Mesa/src/gallium/state_trackers/dri/common/dri_drawable.c @@ -231,11 +231,11 @@ dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, if (format == __DRI_TEXTURE_FORMAT_RGB) { /* only need to cover the formats recognized by dri_fill_st_visual */ switch (internal_format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - internal_format = PIPE_FORMAT_B8G8R8X8_UNORM; + case PIPE_FORMAT_BGRA8888_UNORM: + internal_format = PIPE_FORMAT_BGRX8888_UNORM; break; - case PIPE_FORMAT_A8R8G8B8_UNORM: - internal_format = PIPE_FORMAT_X8R8G8B8_UNORM; + case PIPE_FORMAT_ARGB8888_UNORM: + internal_format = PIPE_FORMAT_XRGB8888_UNORM; break; default: break; diff --git a/dist/Mesa/src/gallium/state_trackers/dri/drm/dri2.c b/dist/Mesa/src/gallium/state_trackers/dri/drm/dri2.c index d02736a06..6308d35e0 100644 --- a/dist/Mesa/src/gallium/state_trackers/dri/drm/dri2.c +++ b/dist/Mesa/src/gallium/state_trackers/dri/drm/dri2.c @@ -162,10 +162,10 @@ dri2_drawable_get_buffers(struct dri_drawable *drawable, * may occur as the stvis->color_format. */ switch(format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: + case PIPE_FORMAT_BGRA8888_UNORM: depth = 32; break; - case PIPE_FORMAT_B8G8R8X8_UNORM: + case PIPE_FORMAT_BGRX8888_UNORM: depth = 24; break; case PIPE_FORMAT_B5G6R5_UNORM: @@ -444,10 +444,10 @@ dri2_allocate_buffer(__DRIscreen *sPriv, switch (format) { case 32: - pf = PIPE_FORMAT_B8G8R8A8_UNORM; + pf = PIPE_FORMAT_BGRA8888_UNORM; break; case 24: - pf = PIPE_FORMAT_B8G8R8X8_UNORM; + pf = PIPE_FORMAT_BGRX8888_UNORM; break; case 16: pf = PIPE_FORMAT_Z16_UNORM; @@ -590,13 +590,13 @@ dri2_create_image_from_winsys(__DRIscreen *_screen, pf = PIPE_FORMAT_B5G6R5_UNORM; break; case __DRI_IMAGE_FORMAT_XRGB8888: - pf = PIPE_FORMAT_B8G8R8X8_UNORM; + pf = PIPE_FORMAT_BGRX8888_UNORM; break; case __DRI_IMAGE_FORMAT_ARGB8888: - pf = PIPE_FORMAT_B8G8R8A8_UNORM; + pf = PIPE_FORMAT_BGRA8888_UNORM; break; case __DRI_IMAGE_FORMAT_ABGR8888: - pf = PIPE_FORMAT_R8G8B8A8_UNORM; + pf = PIPE_FORMAT_RGBA8888_UNORM; break; default: pf = PIPE_FORMAT_NONE; @@ -711,13 +711,13 @@ dri2_create_image(__DRIscreen *_screen, pf = PIPE_FORMAT_B5G6R5_UNORM; break; case __DRI_IMAGE_FORMAT_XRGB8888: - pf = PIPE_FORMAT_B8G8R8X8_UNORM; + pf = PIPE_FORMAT_BGRX8888_UNORM; break; case __DRI_IMAGE_FORMAT_ARGB8888: - pf = PIPE_FORMAT_B8G8R8A8_UNORM; + pf = PIPE_FORMAT_BGRA8888_UNORM; break; case __DRI_IMAGE_FORMAT_ABGR8888: - pf = PIPE_FORMAT_R8G8B8A8_UNORM; + pf = PIPE_FORMAT_RGBA8888_UNORM; break; default: pf = PIPE_FORMAT_NONE;