1cdc920a0Smrg/* 2cdc920a0Smrg * Copyright 2009 Marek Olšák <maraeo@gmail.com> 3cdc920a0Smrg * 4cdc920a0Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5cdc920a0Smrg * copy of this software and associated documentation files (the "Software"), 6cdc920a0Smrg * to deal in the Software without restriction, including without limitation 7cdc920a0Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 8cdc920a0Smrg * license, and/or sell copies of the Software, and to permit persons to whom 9cdc920a0Smrg * the Software is furnished to do so, subject to the following conditions: 10cdc920a0Smrg * 11cdc920a0Smrg * The above copyright notice and this permission notice (including the next 12cdc920a0Smrg * paragraph) shall be included in all copies or substantial portions of the 13cdc920a0Smrg * Software. 14cdc920a0Smrg * 15cdc920a0Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16cdc920a0Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17cdc920a0Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18cdc920a0Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19cdc920a0Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20cdc920a0Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21cdc920a0Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 22cdc920a0Smrg 23cdc920a0Smrg#include "r300_context.h" 243464ebd5Sriastradh#include "r300_emit.h" 25cdc920a0Smrg#include "r300_texture.h" 26af69d88dSmrg#include "r300_reg.h" 27cdc920a0Smrg 287ec681f3Smrg#include "util/format/u_format.h" 297ec681f3Smrg#include "util/half_float.h" 303464ebd5Sriastradh#include "util/u_pack_color.h" 313464ebd5Sriastradh#include "util/u_surface.h" 32cdc920a0Smrg 333464ebd5Sriastradhenum r300_blitter_op /* bitmask */ 34cdc920a0Smrg{ 353464ebd5Sriastradh R300_STOP_QUERY = 1, 363464ebd5Sriastradh R300_SAVE_TEXTURES = 2, 373464ebd5Sriastradh R300_SAVE_FRAMEBUFFER = 4, 383464ebd5Sriastradh R300_IGNORE_RENDER_COND = 8, 393464ebd5Sriastradh 403464ebd5Sriastradh R300_CLEAR = R300_STOP_QUERY, 413464ebd5Sriastradh 423464ebd5Sriastradh R300_CLEAR_SURFACE = R300_STOP_QUERY | R300_SAVE_FRAMEBUFFER, 433464ebd5Sriastradh 443464ebd5Sriastradh R300_COPY = R300_STOP_QUERY | R300_SAVE_FRAMEBUFFER | 453464ebd5Sriastradh R300_SAVE_TEXTURES | R300_IGNORE_RENDER_COND, 463464ebd5Sriastradh 47af69d88dSmrg R300_BLIT = R300_STOP_QUERY | R300_SAVE_FRAMEBUFFER | 48af69d88dSmrg R300_SAVE_TEXTURES, 49af69d88dSmrg 503464ebd5Sriastradh R300_DECOMPRESS = R300_STOP_QUERY | R300_IGNORE_RENDER_COND, 513464ebd5Sriastradh}; 523464ebd5Sriastradh 533464ebd5Sriastradhstatic void r300_blitter_begin(struct r300_context* r300, enum r300_blitter_op op) 543464ebd5Sriastradh{ 553464ebd5Sriastradh if ((op & R300_STOP_QUERY) && r300->query_current) { 563464ebd5Sriastradh r300->blitter_saved_query = r300->query_current; 573464ebd5Sriastradh r300_stop_query(r300); 583464ebd5Sriastradh } 593464ebd5Sriastradh 603464ebd5Sriastradh /* Yeah we have to save all those states to ensure the blitter operation 613464ebd5Sriastradh * is really transparent. The states will be restored by the blitter once 623464ebd5Sriastradh * copying is done. */ 63cdc920a0Smrg util_blitter_save_blend(r300->blitter, r300->blend_state.state); 64cdc920a0Smrg util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state.state); 65cdc920a0Smrg util_blitter_save_stencil_ref(r300->blitter, &(r300->stencil_ref)); 66cdc920a0Smrg util_blitter_save_rasterizer(r300->blitter, r300->rs_state.state); 673464ebd5Sriastradh util_blitter_save_fragment_shader(r300->blitter, r300->fs.state); 68cdc920a0Smrg util_blitter_save_vertex_shader(r300->blitter, r300->vs_state.state); 69cdc920a0Smrg util_blitter_save_viewport(r300->blitter, &r300->viewport); 70af69d88dSmrg util_blitter_save_scissor(r300->blitter, r300->scissor_state.state); 71af69d88dSmrg util_blitter_save_sample_mask(r300->blitter, *(unsigned*)r300->sample_mask.state); 72af69d88dSmrg util_blitter_save_vertex_buffer_slot(r300->blitter, r300->vertex_buffer); 733464ebd5Sriastradh util_blitter_save_vertex_elements(r300->blitter, r300->velems); 743464ebd5Sriastradh 753464ebd5Sriastradh if (op & R300_SAVE_FRAMEBUFFER) { 763464ebd5Sriastradh util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); 773464ebd5Sriastradh } 783464ebd5Sriastradh 793464ebd5Sriastradh if (op & R300_SAVE_TEXTURES) { 803464ebd5Sriastradh struct r300_textures_state* state = 813464ebd5Sriastradh (struct r300_textures_state*)r300->textures_state.state; 823464ebd5Sriastradh 833464ebd5Sriastradh util_blitter_save_fragment_sampler_states( 843464ebd5Sriastradh r300->blitter, state->sampler_state_count, 853464ebd5Sriastradh (void**)state->sampler_states); 863464ebd5Sriastradh 873464ebd5Sriastradh util_blitter_save_fragment_sampler_views( 883464ebd5Sriastradh r300->blitter, state->sampler_view_count, 893464ebd5Sriastradh (struct pipe_sampler_view**)state->sampler_views); 903464ebd5Sriastradh } 913464ebd5Sriastradh 923464ebd5Sriastradh if (op & R300_IGNORE_RENDER_COND) { 933464ebd5Sriastradh /* Save the flag. */ 943464ebd5Sriastradh r300->blitter_saved_skip_rendering = r300->skip_rendering+1; 953464ebd5Sriastradh r300->skip_rendering = FALSE; 963464ebd5Sriastradh } else { 973464ebd5Sriastradh r300->blitter_saved_skip_rendering = 0; 983464ebd5Sriastradh } 993464ebd5Sriastradh} 1003464ebd5Sriastradh 1013464ebd5Sriastradhstatic void r300_blitter_end(struct r300_context *r300) 1023464ebd5Sriastradh{ 1033464ebd5Sriastradh if (r300->blitter_saved_query) { 1043464ebd5Sriastradh r300_resume_query(r300, r300->blitter_saved_query); 1053464ebd5Sriastradh r300->blitter_saved_query = NULL; 1063464ebd5Sriastradh } 1073464ebd5Sriastradh 1083464ebd5Sriastradh if (r300->blitter_saved_skip_rendering) { 1093464ebd5Sriastradh /* Restore the flag. */ 1103464ebd5Sriastradh r300->skip_rendering = r300->blitter_saved_skip_rendering-1; 1113464ebd5Sriastradh } 1123464ebd5Sriastradh} 1133464ebd5Sriastradh 1143464ebd5Sriastradhstatic uint32_t r300_depth_clear_cb_value(enum pipe_format format, 1153464ebd5Sriastradh const float* rgba) 1163464ebd5Sriastradh{ 1173464ebd5Sriastradh union util_color uc; 1183464ebd5Sriastradh util_pack_color(rgba, format, &uc); 1193464ebd5Sriastradh 1203464ebd5Sriastradh if (util_format_get_blocksizebits(format) == 32) 121af69d88dSmrg return uc.ui[0]; 1223464ebd5Sriastradh else 1233464ebd5Sriastradh return uc.us | (uc.us << 16); 1243464ebd5Sriastradh} 1253464ebd5Sriastradh 1263464ebd5Sriastradhstatic boolean r300_cbzb_clear_allowed(struct r300_context *r300, 1273464ebd5Sriastradh unsigned clear_buffers) 1283464ebd5Sriastradh{ 1293464ebd5Sriastradh struct pipe_framebuffer_state *fb = 1303464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 1313464ebd5Sriastradh 1323464ebd5Sriastradh /* Only color clear allowed, and only one colorbuffer. */ 133af69d88dSmrg if ((clear_buffers & ~PIPE_CLEAR_COLOR) != 0 || fb->nr_cbufs != 1 || !fb->cbufs[0]) 1343464ebd5Sriastradh return FALSE; 1353464ebd5Sriastradh 1363464ebd5Sriastradh return r300_surface(fb->cbufs[0])->cbzb_allowed; 1373464ebd5Sriastradh} 1383464ebd5Sriastradh 139af69d88dSmrgstatic boolean r300_fast_zclear_allowed(struct r300_context *r300, 140af69d88dSmrg unsigned clear_buffers) 1413464ebd5Sriastradh{ 1423464ebd5Sriastradh struct pipe_framebuffer_state *fb = 1433464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 1443464ebd5Sriastradh 1453464ebd5Sriastradh return r300_resource(fb->zsbuf->texture)->tex.zmask_dwords[fb->zsbuf->u.tex.level] != 0; 1463464ebd5Sriastradh} 1473464ebd5Sriastradh 1483464ebd5Sriastradhstatic boolean r300_hiz_clear_allowed(struct r300_context *r300) 1493464ebd5Sriastradh{ 1503464ebd5Sriastradh struct pipe_framebuffer_state *fb = 1513464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 1523464ebd5Sriastradh 1533464ebd5Sriastradh return r300_resource(fb->zsbuf->texture)->tex.hiz_dwords[fb->zsbuf->u.tex.level] != 0; 1543464ebd5Sriastradh} 1553464ebd5Sriastradh 1563464ebd5Sriastradhstatic uint32_t r300_depth_clear_value(enum pipe_format format, 1573464ebd5Sriastradh double depth, unsigned stencil) 1583464ebd5Sriastradh{ 1593464ebd5Sriastradh switch (format) { 1603464ebd5Sriastradh case PIPE_FORMAT_Z16_UNORM: 1613464ebd5Sriastradh case PIPE_FORMAT_X8Z24_UNORM: 1623464ebd5Sriastradh return util_pack_z(format, depth); 1633464ebd5Sriastradh 164af69d88dSmrg case PIPE_FORMAT_S8_UINT_Z24_UNORM: 1653464ebd5Sriastradh return util_pack_z_stencil(format, depth, stencil); 1663464ebd5Sriastradh 1673464ebd5Sriastradh default: 1683464ebd5Sriastradh assert(0); 1693464ebd5Sriastradh return 0; 1703464ebd5Sriastradh } 1713464ebd5Sriastradh} 1723464ebd5Sriastradh 1733464ebd5Sriastradhstatic uint32_t r300_hiz_clear_value(double depth) 1743464ebd5Sriastradh{ 1753464ebd5Sriastradh uint32_t r = (uint32_t)(CLAMP(depth, 0, 1) * 255.5); 1763464ebd5Sriastradh assert(r <= 255); 1773464ebd5Sriastradh return r | (r << 8) | (r << 16) | (r << 24); 178cdc920a0Smrg} 179cdc920a0Smrg 180af69d88dSmrgstatic void r300_set_clear_color(struct r300_context *r300, 181af69d88dSmrg const union pipe_color_union *color) 182af69d88dSmrg{ 183af69d88dSmrg struct pipe_framebuffer_state *fb = 184af69d88dSmrg (struct pipe_framebuffer_state*)r300->fb_state.state; 185af69d88dSmrg union util_color uc; 186af69d88dSmrg 187af69d88dSmrg memset(&uc, 0, sizeof(uc)); 188af69d88dSmrg util_pack_color(color->f, fb->cbufs[0]->format, &uc); 189af69d88dSmrg 190af69d88dSmrg if (fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16A16_FLOAT || 191af69d88dSmrg fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16X16_FLOAT) { 192af69d88dSmrg /* (0,1,2,3) maps to (B,G,R,A) */ 193af69d88dSmrg r300->color_clear_value_gb = uc.h[0] | ((uint32_t)uc.h[1] << 16); 194af69d88dSmrg r300->color_clear_value_ar = uc.h[2] | ((uint32_t)uc.h[3] << 16); 195af69d88dSmrg } else { 196af69d88dSmrg r300->color_clear_value = uc.ui[0]; 197af69d88dSmrg } 198af69d88dSmrg} 199af69d88dSmrg 200af69d88dSmrgDEBUG_GET_ONCE_BOOL_OPTION(hyperz, "RADEON_HYPERZ", FALSE) 201af69d88dSmrg 202cdc920a0Smrg/* Clear currently bound buffers. */ 2033464ebd5Sriastradhstatic void r300_clear(struct pipe_context* pipe, 2043464ebd5Sriastradh unsigned buffers, 2057ec681f3Smrg const struct pipe_scissor_state *scissor_state, 206af69d88dSmrg const union pipe_color_union *color, 2073464ebd5Sriastradh double depth, 2083464ebd5Sriastradh unsigned stencil) 209cdc920a0Smrg{ 2103464ebd5Sriastradh /* My notes about Zbuffer compression: 211cdc920a0Smrg * 2123464ebd5Sriastradh * 1) The zbuffer must be micro-tiled and whole microtiles must be 2133464ebd5Sriastradh * written if compression is enabled. If microtiling is disabled, 2143464ebd5Sriastradh * it locks up. 215cdc920a0Smrg * 2163464ebd5Sriastradh * 2) There is ZMASK RAM which contains a compressed zbuffer. 2173464ebd5Sriastradh * Each dword of the Z Mask contains compression information 2183464ebd5Sriastradh * for 16 4x4 pixel tiles, that is 2 bits for each tile. 2193464ebd5Sriastradh * On chips with 2 Z pipes, every other dword maps to a different 2203464ebd5Sriastradh * pipe. On newer chipsets, there is a new compression mode 2213464ebd5Sriastradh * with 8x8 pixel tiles per 2 bits. 222cdc920a0Smrg * 2233464ebd5Sriastradh * 3) The FASTFILL bit has nothing to do with filling. It only tells hw 2243464ebd5Sriastradh * it should look in the ZMASK RAM first before fetching from a real 2253464ebd5Sriastradh * zbuffer. 226cdc920a0Smrg * 2273464ebd5Sriastradh * 4) If a pixel is in a cleared state, ZB_DEPTHCLEARVALUE is returned 2283464ebd5Sriastradh * during zbuffer reads instead of the value that is actually stored 2293464ebd5Sriastradh * in the zbuffer memory. A pixel is in a cleared state when its ZMASK 2303464ebd5Sriastradh * is equal to 0. Therefore, if you clear ZMASK with zeros, you may 2313464ebd5Sriastradh * leave the zbuffer memory uninitialized, but then you must enable 2323464ebd5Sriastradh * compression, so that the ZMASK RAM is actually used. 233cdc920a0Smrg * 2343464ebd5Sriastradh * 5) Each 4x4 (or 8x8) tile is automatically decompressed and recompressed 2353464ebd5Sriastradh * during zbuffer updates. A special decompressing operation should be 2363464ebd5Sriastradh * used to fully decompress a zbuffer, which basically just stores all 2373464ebd5Sriastradh * compressed tiles in ZMASK to the zbuffer memory. 238cdc920a0Smrg * 2393464ebd5Sriastradh * 6) For a 16-bit zbuffer, compression causes a hung with one or 240cdc920a0Smrg * two samples and should not be used. 241cdc920a0Smrg * 2423464ebd5Sriastradh * 7) FORCE_COMPRESSED_STENCIL_VALUE should be enabled for stencil clears 2433464ebd5Sriastradh * to avoid needless decompression. 2443464ebd5Sriastradh * 2453464ebd5Sriastradh * 8) Fastfill must not be used if reading of compressed Z data is disabled 246cdc920a0Smrg * and writing of compressed Z data is enabled (RD/WR_COMP_ENABLE), 247cdc920a0Smrg * i.e. it cannot be used to compress the zbuffer. 2483464ebd5Sriastradh * 2493464ebd5Sriastradh * 9) ZB_CB_CLEAR does not interact with zbuffer compression in any way. 250cdc920a0Smrg * 251cdc920a0Smrg * - Marek 252cdc920a0Smrg */ 253cdc920a0Smrg 254cdc920a0Smrg struct r300_context* r300 = r300_context(pipe); 2553464ebd5Sriastradh struct pipe_framebuffer_state *fb = 2563464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 2573464ebd5Sriastradh struct r300_hyperz_state *hyperz = 2583464ebd5Sriastradh (struct r300_hyperz_state*)r300->hyperz_state.state; 2593464ebd5Sriastradh uint32_t width = fb->width; 2603464ebd5Sriastradh uint32_t height = fb->height; 2613464ebd5Sriastradh uint32_t hyperz_dcv = hyperz->zb_depthclearvalue; 2623464ebd5Sriastradh 263af69d88dSmrg /* Use fast Z clear. 2643464ebd5Sriastradh * The zbuffer must be in micro-tiled mode, otherwise it locks up. */ 2653464ebd5Sriastradh if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { 2663464ebd5Sriastradh boolean zmask_clear, hiz_clear; 2673464ebd5Sriastradh 268af69d88dSmrg /* If both depth and stencil are present, they must be cleared together. */ 269af69d88dSmrg if (fb->zsbuf->texture->format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 270af69d88dSmrg (buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) { 271af69d88dSmrg zmask_clear = FALSE; 272af69d88dSmrg hiz_clear = FALSE; 273af69d88dSmrg } else { 274af69d88dSmrg zmask_clear = r300_fast_zclear_allowed(r300, buffers); 275af69d88dSmrg hiz_clear = r300_hiz_clear_allowed(r300); 276af69d88dSmrg } 2773464ebd5Sriastradh 2783464ebd5Sriastradh /* If we need Hyper-Z. */ 2793464ebd5Sriastradh if (zmask_clear || hiz_clear) { 2803464ebd5Sriastradh /* Try to obtain the access to Hyper-Z buffers if we don't have one. */ 281af69d88dSmrg if (!r300->hyperz_enabled && 282af69d88dSmrg (r300->screen->caps.is_r500 || debug_get_option_hyperz())) { 2833464ebd5Sriastradh r300->hyperz_enabled = 2847ec681f3Smrg r300->rws->cs_request_feature(&r300->cs, 285af69d88dSmrg RADEON_FID_R300_HYPERZ_ACCESS, 2863464ebd5Sriastradh TRUE); 2873464ebd5Sriastradh if (r300->hyperz_enabled) { 2883464ebd5Sriastradh /* Need to emit HyperZ buffer regs for the first time. */ 2893464ebd5Sriastradh r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); 2903464ebd5Sriastradh } 2913464ebd5Sriastradh } 2923464ebd5Sriastradh 2933464ebd5Sriastradh /* Setup Hyper-Z clears. */ 2943464ebd5Sriastradh if (r300->hyperz_enabled) { 2953464ebd5Sriastradh if (zmask_clear) { 2963464ebd5Sriastradh hyperz_dcv = hyperz->zb_depthclearvalue = 2973464ebd5Sriastradh r300_depth_clear_value(fb->zsbuf->format, depth, stencil); 2983464ebd5Sriastradh 2993464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->zmask_clear); 300af69d88dSmrg r300_mark_atom_dirty(r300, &r300->gpu_flush); 3013464ebd5Sriastradh buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; 3023464ebd5Sriastradh } 3033464ebd5Sriastradh 3043464ebd5Sriastradh if (hiz_clear) { 3053464ebd5Sriastradh r300->hiz_clear_value = r300_hiz_clear_value(depth); 3063464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->hiz_clear); 307af69d88dSmrg r300_mark_atom_dirty(r300, &r300->gpu_flush); 3083464ebd5Sriastradh } 309af69d88dSmrg r300->num_z_clears++; 3103464ebd5Sriastradh } 3113464ebd5Sriastradh } 3123464ebd5Sriastradh } 3133464ebd5Sriastradh 314af69d88dSmrg /* Use fast color clear for an AA colorbuffer. 315af69d88dSmrg * The CMASK is shared between all colorbuffers, so we use it 316af69d88dSmrg * if there is only one colorbuffer bound. */ 317af69d88dSmrg if ((buffers & PIPE_CLEAR_COLOR) && fb->nr_cbufs == 1 && fb->cbufs[0] && 318af69d88dSmrg r300_resource(fb->cbufs[0]->texture)->tex.cmask_dwords) { 319af69d88dSmrg /* Try to obtain the access to the CMASK if we don't have one. */ 320af69d88dSmrg if (!r300->cmask_access) { 321af69d88dSmrg r300->cmask_access = 3227ec681f3Smrg r300->rws->cs_request_feature(&r300->cs, 323af69d88dSmrg RADEON_FID_R300_CMASK_ACCESS, 324af69d88dSmrg TRUE); 325af69d88dSmrg } 326af69d88dSmrg 327af69d88dSmrg /* Setup the clear. */ 328af69d88dSmrg if (r300->cmask_access) { 329af69d88dSmrg /* Pair the resource with the CMASK to avoid other resources 330af69d88dSmrg * accessing it. */ 331af69d88dSmrg if (!r300->screen->cmask_resource) { 33201e04c3fSmrg mtx_lock(&r300->screen->cmask_mutex); 333af69d88dSmrg /* Double checking (first unlocked, then locked). */ 334af69d88dSmrg if (!r300->screen->cmask_resource) { 335af69d88dSmrg /* Don't reference this, so that the texture can be 336af69d88dSmrg * destroyed while set in cmask_resource. 337af69d88dSmrg * Then in texture_destroy, we set cmask_resource to NULL. */ 338af69d88dSmrg r300->screen->cmask_resource = fb->cbufs[0]->texture; 339af69d88dSmrg } 34001e04c3fSmrg mtx_unlock(&r300->screen->cmask_mutex); 341af69d88dSmrg } 342af69d88dSmrg 343af69d88dSmrg if (r300->screen->cmask_resource == fb->cbufs[0]->texture) { 344af69d88dSmrg r300_set_clear_color(r300, color); 345af69d88dSmrg r300_mark_atom_dirty(r300, &r300->cmask_clear); 346af69d88dSmrg r300_mark_atom_dirty(r300, &r300->gpu_flush); 347af69d88dSmrg buffers &= ~PIPE_CLEAR_COLOR; 348af69d88dSmrg } 349af69d88dSmrg } 350af69d88dSmrg } 3513464ebd5Sriastradh /* Enable CBZB clear. */ 352af69d88dSmrg else if (r300_cbzb_clear_allowed(r300, buffers)) { 3533464ebd5Sriastradh struct r300_surface *surf = r300_surface(fb->cbufs[0]); 3543464ebd5Sriastradh 3553464ebd5Sriastradh hyperz->zb_depthclearvalue = 356af69d88dSmrg r300_depth_clear_cb_value(surf->base.format, color->f); 3573464ebd5Sriastradh 3583464ebd5Sriastradh width = surf->cbzb_width; 3593464ebd5Sriastradh height = surf->cbzb_height; 3603464ebd5Sriastradh 3613464ebd5Sriastradh r300->cbzb_clear = TRUE; 3623464ebd5Sriastradh r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); 3633464ebd5Sriastradh } 3643464ebd5Sriastradh 3653464ebd5Sriastradh /* Clear. */ 3663464ebd5Sriastradh if (buffers) { 3673464ebd5Sriastradh /* Clear using the blitter. */ 3683464ebd5Sriastradh r300_blitter_begin(r300, R300_CLEAR); 369af69d88dSmrg util_blitter_clear(r300->blitter, width, height, 1, 3707ec681f3Smrg buffers, color, depth, stencil, 3717ec681f3Smrg util_framebuffer_get_num_samples(fb) > 1); 3723464ebd5Sriastradh r300_blitter_end(r300); 373af69d88dSmrg } else if (r300->zmask_clear.dirty || 374af69d88dSmrg r300->hiz_clear.dirty || 375af69d88dSmrg r300->cmask_clear.dirty) { 3763464ebd5Sriastradh /* Just clear zmask and hiz now, this does not use the standard draw 3773464ebd5Sriastradh * procedure. */ 3783464ebd5Sriastradh /* Calculate zmask_clear and hiz_clear atom sizes. */ 3793464ebd5Sriastradh unsigned dwords = 380af69d88dSmrg r300->gpu_flush.size + 3813464ebd5Sriastradh (r300->zmask_clear.dirty ? r300->zmask_clear.size : 0) + 3823464ebd5Sriastradh (r300->hiz_clear.dirty ? r300->hiz_clear.size : 0) + 383af69d88dSmrg (r300->cmask_clear.dirty ? r300->cmask_clear.size : 0) + 3843464ebd5Sriastradh r300_get_num_cs_end_dwords(r300); 3853464ebd5Sriastradh 3863464ebd5Sriastradh /* Reserve CS space. */ 3877ec681f3Smrg if (!r300->rws->cs_check_space(&r300->cs, dwords, false)) { 38801e04c3fSmrg r300_flush(&r300->context, PIPE_FLUSH_ASYNC, NULL); 3893464ebd5Sriastradh } 3903464ebd5Sriastradh 3913464ebd5Sriastradh /* Emit clear packets. */ 392af69d88dSmrg r300_emit_gpu_flush(r300, r300->gpu_flush.size, r300->gpu_flush.state); 393af69d88dSmrg r300->gpu_flush.dirty = FALSE; 394af69d88dSmrg 3953464ebd5Sriastradh if (r300->zmask_clear.dirty) { 3963464ebd5Sriastradh r300_emit_zmask_clear(r300, r300->zmask_clear.size, 3973464ebd5Sriastradh r300->zmask_clear.state); 3983464ebd5Sriastradh r300->zmask_clear.dirty = FALSE; 3993464ebd5Sriastradh } 4003464ebd5Sriastradh if (r300->hiz_clear.dirty) { 4013464ebd5Sriastradh r300_emit_hiz_clear(r300, r300->hiz_clear.size, 4023464ebd5Sriastradh r300->hiz_clear.state); 4033464ebd5Sriastradh r300->hiz_clear.dirty = FALSE; 4043464ebd5Sriastradh } 405af69d88dSmrg if (r300->cmask_clear.dirty) { 406af69d88dSmrg r300_emit_cmask_clear(r300, r300->cmask_clear.size, 407af69d88dSmrg r300->cmask_clear.state); 408af69d88dSmrg r300->cmask_clear.dirty = FALSE; 409af69d88dSmrg } 4103464ebd5Sriastradh } else { 4113464ebd5Sriastradh assert(0); 4123464ebd5Sriastradh } 4133464ebd5Sriastradh 4143464ebd5Sriastradh /* Disable CBZB clear. */ 4153464ebd5Sriastradh if (r300->cbzb_clear) { 4163464ebd5Sriastradh r300->cbzb_clear = FALSE; 4173464ebd5Sriastradh hyperz->zb_depthclearvalue = hyperz_dcv; 4183464ebd5Sriastradh r300_mark_fb_state_dirty(r300, R300_CHANGED_HYPERZ_FLAG); 4193464ebd5Sriastradh } 4203464ebd5Sriastradh 4213464ebd5Sriastradh /* Enable fastfill and/or hiz. 4223464ebd5Sriastradh * 4233464ebd5Sriastradh * If we cleared zmask/hiz, it's in use now. The Hyper-Z state update 4243464ebd5Sriastradh * looks if zmask/hiz is in use and programs hardware accordingly. */ 4253464ebd5Sriastradh if (r300->zmask_in_use || r300->hiz_in_use) { 4263464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->hyperz_state); 4273464ebd5Sriastradh } 4283464ebd5Sriastradh} 4293464ebd5Sriastradh 4303464ebd5Sriastradh/* Clear a region of a color surface to a constant value. */ 4313464ebd5Sriastradhstatic void r300_clear_render_target(struct pipe_context *pipe, 4323464ebd5Sriastradh struct pipe_surface *dst, 433af69d88dSmrg const union pipe_color_union *color, 4343464ebd5Sriastradh unsigned dstx, unsigned dsty, 43501e04c3fSmrg unsigned width, unsigned height, 43601e04c3fSmrg bool render_condition_enabled) 4373464ebd5Sriastradh{ 4383464ebd5Sriastradh struct r300_context *r300 = r300_context(pipe); 4393464ebd5Sriastradh 44001e04c3fSmrg r300_blitter_begin(r300, R300_CLEAR_SURFACE | 44101e04c3fSmrg (render_condition_enabled ? 0 : R300_IGNORE_RENDER_COND)); 442af69d88dSmrg util_blitter_clear_render_target(r300->blitter, dst, color, 4433464ebd5Sriastradh dstx, dsty, width, height); 4443464ebd5Sriastradh r300_blitter_end(r300); 4453464ebd5Sriastradh} 4463464ebd5Sriastradh 4473464ebd5Sriastradh/* Clear a region of a depth stencil surface. */ 4483464ebd5Sriastradhstatic void r300_clear_depth_stencil(struct pipe_context *pipe, 4493464ebd5Sriastradh struct pipe_surface *dst, 4503464ebd5Sriastradh unsigned clear_flags, 4513464ebd5Sriastradh double depth, 4523464ebd5Sriastradh unsigned stencil, 4533464ebd5Sriastradh unsigned dstx, unsigned dsty, 45401e04c3fSmrg unsigned width, unsigned height, 45501e04c3fSmrg bool render_condition_enabled) 4563464ebd5Sriastradh{ 4573464ebd5Sriastradh struct r300_context *r300 = r300_context(pipe); 4583464ebd5Sriastradh struct pipe_framebuffer_state *fb = 459cdc920a0Smrg (struct pipe_framebuffer_state*)r300->fb_state.state; 460cdc920a0Smrg 4613464ebd5Sriastradh if (r300->zmask_in_use && !r300->locked_zbuffer) { 4623464ebd5Sriastradh if (fb->zsbuf->texture == dst->texture) { 4633464ebd5Sriastradh r300_decompress_zmask(r300); 4643464ebd5Sriastradh } 4653464ebd5Sriastradh } 466cdc920a0Smrg 4673464ebd5Sriastradh /* XXX Do not decompress ZMask of the currently-set zbuffer. */ 46801e04c3fSmrg r300_blitter_begin(r300, R300_CLEAR_SURFACE | 46901e04c3fSmrg (render_condition_enabled ? 0 : R300_IGNORE_RENDER_COND)); 4703464ebd5Sriastradh util_blitter_clear_depth_stencil(r300->blitter, dst, clear_flags, depth, stencil, 4713464ebd5Sriastradh dstx, dsty, width, height); 4723464ebd5Sriastradh r300_blitter_end(r300); 473cdc920a0Smrg} 474cdc920a0Smrg 4753464ebd5Sriastradhvoid r300_decompress_zmask(struct r300_context *r300) 476cdc920a0Smrg{ 4773464ebd5Sriastradh struct pipe_framebuffer_state *fb = 4783464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 479cdc920a0Smrg 4803464ebd5Sriastradh if (!r300->zmask_in_use || r300->locked_zbuffer) 4813464ebd5Sriastradh return; 4823464ebd5Sriastradh 4833464ebd5Sriastradh r300->zmask_decompress = TRUE; 4843464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->hyperz_state); 4853464ebd5Sriastradh 4863464ebd5Sriastradh r300_blitter_begin(r300, R300_DECOMPRESS); 487af69d88dSmrg util_blitter_custom_clear_depth(r300->blitter, fb->width, fb->height, 0, 4883464ebd5Sriastradh r300->dsa_decompress_zmask); 4893464ebd5Sriastradh r300_blitter_end(r300); 4903464ebd5Sriastradh 4913464ebd5Sriastradh r300->zmask_decompress = FALSE; 4923464ebd5Sriastradh r300->zmask_in_use = FALSE; 4933464ebd5Sriastradh r300_mark_atom_dirty(r300, &r300->hyperz_state); 4943464ebd5Sriastradh} 4953464ebd5Sriastradh 4963464ebd5Sriastradhvoid r300_decompress_zmask_locked_unsafe(struct r300_context *r300) 4973464ebd5Sriastradh{ 498af69d88dSmrg struct pipe_framebuffer_state fb; 499af69d88dSmrg 500af69d88dSmrg memset(&fb, 0, sizeof(fb)); 5013464ebd5Sriastradh fb.width = r300->locked_zbuffer->width; 5023464ebd5Sriastradh fb.height = r300->locked_zbuffer->height; 5033464ebd5Sriastradh fb.zsbuf = r300->locked_zbuffer; 504cdc920a0Smrg 5053464ebd5Sriastradh r300->context.set_framebuffer_state(&r300->context, &fb); 5063464ebd5Sriastradh r300_decompress_zmask(r300); 5073464ebd5Sriastradh} 5083464ebd5Sriastradh 5093464ebd5Sriastradhvoid r300_decompress_zmask_locked(struct r300_context *r300) 5103464ebd5Sriastradh{ 511af69d88dSmrg struct pipe_framebuffer_state saved_fb; 512cdc920a0Smrg 513af69d88dSmrg memset(&saved_fb, 0, sizeof(saved_fb)); 5143464ebd5Sriastradh util_copy_framebuffer_state(&saved_fb, r300->fb_state.state); 5153464ebd5Sriastradh r300_decompress_zmask_locked_unsafe(r300); 5163464ebd5Sriastradh r300->context.set_framebuffer_state(&r300->context, &saved_fb); 5173464ebd5Sriastradh util_unreference_framebuffer_state(&saved_fb); 518cdc920a0Smrg 5193464ebd5Sriastradh pipe_surface_reference(&r300->locked_zbuffer, NULL); 5203464ebd5Sriastradh} 5213464ebd5Sriastradh 522af69d88dSmrgbool r300_is_blit_supported(enum pipe_format format) 5233464ebd5Sriastradh{ 524af69d88dSmrg const struct util_format_description *desc = 525af69d88dSmrg util_format_description(format); 5263464ebd5Sriastradh 527af69d88dSmrg return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || 528af69d88dSmrg desc->layout == UTIL_FORMAT_LAYOUT_S3TC || 529af69d88dSmrg desc->layout == UTIL_FORMAT_LAYOUT_RGTC; 530cdc920a0Smrg} 531cdc920a0Smrg 532cdc920a0Smrg/* Copy a block of pixels from one surface to another. */ 5333464ebd5Sriastradhstatic void r300_resource_copy_region(struct pipe_context *pipe, 5343464ebd5Sriastradh struct pipe_resource *dst, 5353464ebd5Sriastradh unsigned dst_level, 5363464ebd5Sriastradh unsigned dstx, unsigned dsty, unsigned dstz, 5373464ebd5Sriastradh struct pipe_resource *src, 5383464ebd5Sriastradh unsigned src_level, 5393464ebd5Sriastradh const struct pipe_box *src_box) 5403464ebd5Sriastradh{ 541af69d88dSmrg struct pipe_screen *screen = pipe->screen; 5423464ebd5Sriastradh struct r300_context *r300 = r300_context(pipe); 5433464ebd5Sriastradh struct pipe_framebuffer_state *fb = 5443464ebd5Sriastradh (struct pipe_framebuffer_state*)r300->fb_state.state; 545af69d88dSmrg unsigned src_width0 = r300_resource(src)->tex.width0; 546af69d88dSmrg unsigned src_height0 = r300_resource(src)->tex.height0; 547af69d88dSmrg unsigned dst_width0 = r300_resource(dst)->tex.width0; 548af69d88dSmrg unsigned dst_height0 = r300_resource(dst)->tex.height0; 549af69d88dSmrg unsigned layout; 550af69d88dSmrg struct pipe_box box, dstbox; 551af69d88dSmrg struct pipe_sampler_view src_templ, *src_view; 552af69d88dSmrg struct pipe_surface dst_templ, *dst_view; 5533464ebd5Sriastradh 5543464ebd5Sriastradh /* Fallback for buffers. */ 555af69d88dSmrg if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) || 556af69d88dSmrg !r300_is_blit_supported(dst->format)) { 5573464ebd5Sriastradh util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, 5583464ebd5Sriastradh src, src_level, src_box); 5593464ebd5Sriastradh return; 5603464ebd5Sriastradh } 5613464ebd5Sriastradh 562af69d88dSmrg /* Can't read MSAA textures. */ 563af69d88dSmrg if (src->nr_samples > 1 || dst->nr_samples > 1) { 564af69d88dSmrg return; 5653464ebd5Sriastradh } 5663464ebd5Sriastradh 567af69d88dSmrg /* The code below changes the texture format so that the copy can be done 568af69d88dSmrg * on hardware. E.g. depth-stencil surfaces are copied as RGBA 569af69d88dSmrg * colorbuffers. */ 570af69d88dSmrg 571af69d88dSmrg util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz); 57201e04c3fSmrg util_blitter_default_src_texture(r300->blitter, &src_templ, src, src_level); 573af69d88dSmrg 574af69d88dSmrg layout = util_format_description(dst_templ.format)->layout; 575af69d88dSmrg 5763464ebd5Sriastradh /* Handle non-renderable plain formats. */ 577af69d88dSmrg if (layout == UTIL_FORMAT_LAYOUT_PLAIN && 578af69d88dSmrg (!screen->is_format_supported(screen, src_templ.format, src->target, 57901e04c3fSmrg src->nr_samples, src->nr_storage_samples, 580af69d88dSmrg PIPE_BIND_SAMPLER_VIEW) || 581af69d88dSmrg !screen->is_format_supported(screen, dst_templ.format, dst->target, 58201e04c3fSmrg dst->nr_samples, dst->nr_storage_samples, 583af69d88dSmrg PIPE_BIND_RENDER_TARGET))) { 584af69d88dSmrg switch (util_format_get_blocksize(dst_templ.format)) { 585cdc920a0Smrg case 1: 586af69d88dSmrg dst_templ.format = PIPE_FORMAT_I8_UNORM; 587cdc920a0Smrg break; 588cdc920a0Smrg case 2: 589af69d88dSmrg dst_templ.format = PIPE_FORMAT_B4G4R4A4_UNORM; 590cdc920a0Smrg break; 591cdc920a0Smrg case 4: 592af69d88dSmrg dst_templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; 5933464ebd5Sriastradh break; 5943464ebd5Sriastradh case 8: 595af69d88dSmrg dst_templ.format = PIPE_FORMAT_R16G16B16A16_UNORM; 596cdc920a0Smrg break; 597cdc920a0Smrg default: 598af69d88dSmrg debug_printf("r300: copy_region: Unhandled format: %s. Falling back to software.\n" 599af69d88dSmrg "r300: copy_region: Software fallback doesn't work for tiled textures.\n", 600af69d88dSmrg util_format_short_name(dst_templ.format)); 601cdc920a0Smrg } 602af69d88dSmrg src_templ.format = dst_templ.format; 603cdc920a0Smrg } 604cdc920a0Smrg 6053464ebd5Sriastradh /* Handle compressed formats. */ 606af69d88dSmrg if (layout == UTIL_FORMAT_LAYOUT_S3TC || 607af69d88dSmrg layout == UTIL_FORMAT_LAYOUT_RGTC) { 608af69d88dSmrg assert(src_templ.format == dst_templ.format); 609af69d88dSmrg 610af69d88dSmrg box = *src_box; 611af69d88dSmrg src_box = &box; 612af69d88dSmrg 613af69d88dSmrg dst_width0 = align(dst_width0, 4); 614af69d88dSmrg dst_height0 = align(dst_height0, 4); 615af69d88dSmrg src_width0 = align(src_width0, 4); 616af69d88dSmrg src_height0 = align(src_height0, 4); 617af69d88dSmrg box.width = align(box.width, 4); 618af69d88dSmrg box.height = align(box.height, 4); 619af69d88dSmrg 620af69d88dSmrg switch (util_format_get_blocksize(dst_templ.format)) { 6213464ebd5Sriastradh case 8: 622af69d88dSmrg /* one 4x4 pixel block has 8 bytes. 623af69d88dSmrg * we set 1 pixel = 4 bytes ===> 1 block corrensponds to 2 pixels. */ 624af69d88dSmrg dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; 625af69d88dSmrg dst_width0 = dst_width0 / 2; 626af69d88dSmrg src_width0 = src_width0 / 2; 627af69d88dSmrg dstx /= 2; 628af69d88dSmrg box.x /= 2; 629af69d88dSmrg box.width /= 2; 6303464ebd5Sriastradh break; 6313464ebd5Sriastradh case 16: 632af69d88dSmrg /* one 4x4 pixel block has 16 bytes. 633af69d88dSmrg * we set 1 pixel = 4 bytes ===> 1 block corresponds to 4 pixels. */ 634af69d88dSmrg dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; 6353464ebd5Sriastradh break; 6363464ebd5Sriastradh } 637af69d88dSmrg src_templ.format = dst_templ.format; 638cdc920a0Smrg 639af69d88dSmrg dst_height0 = dst_height0 / 4; 640af69d88dSmrg src_height0 = src_height0 / 4; 6413464ebd5Sriastradh dsty /= 4; 6423464ebd5Sriastradh box.y /= 4; 643af69d88dSmrg box.height /= 4; 644cdc920a0Smrg } 645cdc920a0Smrg 646af69d88dSmrg /* Fallback for textures. */ 647af69d88dSmrg if (!screen->is_format_supported(screen, dst_templ.format, 648af69d88dSmrg dst->target, dst->nr_samples, 64901e04c3fSmrg dst->nr_storage_samples, 650af69d88dSmrg PIPE_BIND_RENDER_TARGET) || 651af69d88dSmrg !screen->is_format_supported(screen, src_templ.format, 652af69d88dSmrg src->target, src->nr_samples, 65301e04c3fSmrg src->nr_storage_samples, 654af69d88dSmrg PIPE_BIND_SAMPLER_VIEW)) { 655af69d88dSmrg assert(0 && "this shouldn't happen, update r300_is_blit_supported"); 656af69d88dSmrg util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz, 657af69d88dSmrg src, src_level, src_box); 658af69d88dSmrg return; 659af69d88dSmrg } 660cdc920a0Smrg 661af69d88dSmrg /* Decompress ZMASK. */ 662af69d88dSmrg if (r300->zmask_in_use && !r300->locked_zbuffer) { 663af69d88dSmrg if (fb->zsbuf->texture == src || 664af69d88dSmrg fb->zsbuf->texture == dst) { 665af69d88dSmrg r300_decompress_zmask(r300); 666af69d88dSmrg } 667af69d88dSmrg } 668af69d88dSmrg 669af69d88dSmrg dst_view = r300_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0); 670af69d88dSmrg src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0); 671af69d88dSmrg 672af69d88dSmrg u_box_3d(dstx, dsty, dstz, abs(src_box->width), abs(src_box->height), 673af69d88dSmrg abs(src_box->depth), &dstbox); 674af69d88dSmrg 675af69d88dSmrg r300_blitter_begin(r300, R300_COPY); 676af69d88dSmrg util_blitter_blit_generic(r300->blitter, dst_view, &dstbox, 677af69d88dSmrg src_view, src_box, src_width0, src_height0, 67801e04c3fSmrg PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, 6797ec681f3Smrg FALSE, FALSE); 680af69d88dSmrg r300_blitter_end(r300); 681af69d88dSmrg 682af69d88dSmrg pipe_surface_reference(&dst_view, NULL); 683af69d88dSmrg pipe_sampler_view_reference(&src_view, NULL); 684af69d88dSmrg} 685af69d88dSmrg 686af69d88dSmrgstatic boolean r300_is_simple_msaa_resolve(const struct pipe_blit_info *info) 687af69d88dSmrg{ 688af69d88dSmrg unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); 689af69d88dSmrg unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); 690af69d88dSmrg 69101e04c3fSmrg return info->src.resource->nr_samples > 1 && 69201e04c3fSmrg info->dst.resource->nr_samples <= 1 && 69301e04c3fSmrg info->dst.resource->format == info->src.resource->format && 694af69d88dSmrg info->dst.resource->format == info->dst.format && 695af69d88dSmrg info->src.resource->format == info->src.format && 696af69d88dSmrg !info->scissor_enable && 697af69d88dSmrg info->mask == PIPE_MASK_RGBA && 698af69d88dSmrg dst_width == info->src.resource->width0 && 699af69d88dSmrg dst_height == info->src.resource->height0 && 700af69d88dSmrg info->dst.box.x == 0 && 701af69d88dSmrg info->dst.box.y == 0 && 702af69d88dSmrg info->dst.box.width == dst_width && 703af69d88dSmrg info->dst.box.height == dst_height && 704af69d88dSmrg info->src.box.x == 0 && 705af69d88dSmrg info->src.box.y == 0 && 706af69d88dSmrg info->src.box.width == dst_width && 707af69d88dSmrg info->src.box.height == dst_height && 708af69d88dSmrg (r300_resource(info->dst.resource)->tex.microtile != RADEON_LAYOUT_LINEAR || 709af69d88dSmrg r300_resource(info->dst.resource)->tex.macrotile[info->dst.level] != RADEON_LAYOUT_LINEAR); 710af69d88dSmrg} 711af69d88dSmrg 712af69d88dSmrgstatic void r300_simple_msaa_resolve(struct pipe_context *pipe, 713af69d88dSmrg struct pipe_resource *dst, 714af69d88dSmrg unsigned dst_level, 715af69d88dSmrg unsigned dst_layer, 716af69d88dSmrg struct pipe_resource *src, 717af69d88dSmrg enum pipe_format format) 718af69d88dSmrg{ 719af69d88dSmrg struct r300_context *r300 = r300_context(pipe); 720af69d88dSmrg struct r300_surface *srcsurf, *dstsurf; 721af69d88dSmrg struct pipe_surface surf_tmpl; 722af69d88dSmrg struct r300_aa_state *aa = (struct r300_aa_state*)r300->aa_state.state; 723af69d88dSmrg 724af69d88dSmrg memset(&surf_tmpl, 0, sizeof(surf_tmpl)); 725af69d88dSmrg surf_tmpl.format = format; 726af69d88dSmrg srcsurf = r300_surface(pipe->create_surface(pipe, src, &surf_tmpl)); 727af69d88dSmrg 728af69d88dSmrg surf_tmpl.format = format; 729af69d88dSmrg surf_tmpl.u.tex.level = dst_level; 730af69d88dSmrg surf_tmpl.u.tex.first_layer = 731af69d88dSmrg surf_tmpl.u.tex.last_layer = dst_layer; 732af69d88dSmrg dstsurf = r300_surface(pipe->create_surface(pipe, dst, &surf_tmpl)); 733af69d88dSmrg 734af69d88dSmrg /* COLORPITCH should contain the tiling info of the resolve buffer. 735af69d88dSmrg * The tiling of the AA buffer isn't programmable anyway. */ 736af69d88dSmrg srcsurf->pitch &= ~(R300_COLOR_TILE(1) | R300_COLOR_MICROTILE(3)); 737af69d88dSmrg srcsurf->pitch |= dstsurf->pitch & (R300_COLOR_TILE(1) | R300_COLOR_MICROTILE(3)); 738af69d88dSmrg 739af69d88dSmrg /* Enable AA resolve. */ 740af69d88dSmrg aa->dest = dstsurf; 741af69d88dSmrg r300->aa_state.size = 8; 742af69d88dSmrg r300_mark_atom_dirty(r300, &r300->aa_state); 743af69d88dSmrg 744af69d88dSmrg /* Resolve the surface. */ 745af69d88dSmrg r300_blitter_begin(r300, R300_CLEAR_SURFACE); 746af69d88dSmrg util_blitter_custom_color(r300->blitter, &srcsurf->base, NULL); 747af69d88dSmrg r300_blitter_end(r300); 748af69d88dSmrg 749af69d88dSmrg /* Disable AA resolve. */ 750af69d88dSmrg aa->dest = NULL; 751af69d88dSmrg r300->aa_state.size = 4; 752af69d88dSmrg r300_mark_atom_dirty(r300, &r300->aa_state); 753af69d88dSmrg 754af69d88dSmrg pipe_surface_reference((struct pipe_surface**)&srcsurf, NULL); 755af69d88dSmrg pipe_surface_reference((struct pipe_surface**)&dstsurf, NULL); 756af69d88dSmrg} 757af69d88dSmrg 758af69d88dSmrgstatic void r300_msaa_resolve(struct pipe_context *pipe, 759af69d88dSmrg const struct pipe_blit_info *info) 760af69d88dSmrg{ 761af69d88dSmrg struct r300_context *r300 = r300_context(pipe); 762af69d88dSmrg struct pipe_screen *screen = pipe->screen; 763af69d88dSmrg struct pipe_resource *tmp, templ; 764af69d88dSmrg struct pipe_blit_info blit; 765af69d88dSmrg 766af69d88dSmrg assert(info->src.level == 0); 767af69d88dSmrg assert(info->src.box.z == 0); 768af69d88dSmrg assert(info->src.box.depth == 1); 769af69d88dSmrg assert(info->dst.box.depth == 1); 770af69d88dSmrg 771af69d88dSmrg if (r300_is_simple_msaa_resolve(info)) { 772af69d88dSmrg r300_simple_msaa_resolve(pipe, info->dst.resource, info->dst.level, 773af69d88dSmrg info->dst.box.z, info->src.resource, 774af69d88dSmrg info->src.format); 775af69d88dSmrg return; 776af69d88dSmrg } 777af69d88dSmrg 778af69d88dSmrg /* resolve into a temporary texture, then blit */ 779af69d88dSmrg memset(&templ, 0, sizeof(templ)); 780af69d88dSmrg templ.target = PIPE_TEXTURE_2D; 781af69d88dSmrg templ.format = info->src.resource->format; 782af69d88dSmrg templ.width0 = info->src.resource->width0; 783af69d88dSmrg templ.height0 = info->src.resource->height0; 784af69d88dSmrg templ.depth0 = 1; 785af69d88dSmrg templ.array_size = 1; 786af69d88dSmrg templ.usage = PIPE_USAGE_DEFAULT; 787af69d88dSmrg templ.flags = R300_RESOURCE_FORCE_MICROTILING; 788af69d88dSmrg 789af69d88dSmrg tmp = screen->resource_create(screen, &templ); 790af69d88dSmrg 791af69d88dSmrg /* resolve */ 792af69d88dSmrg r300_simple_msaa_resolve(pipe, tmp, 0, 0, info->src.resource, 793af69d88dSmrg info->src.format); 794af69d88dSmrg 795af69d88dSmrg /* blit */ 796af69d88dSmrg blit = *info; 797af69d88dSmrg blit.src.resource = tmp; 798af69d88dSmrg blit.src.box.z = 0; 799af69d88dSmrg 800af69d88dSmrg r300_blitter_begin(r300, R300_BLIT | R300_IGNORE_RENDER_COND); 801af69d88dSmrg util_blitter_blit(r300->blitter, &blit); 802af69d88dSmrg r300_blitter_end(r300); 803cdc920a0Smrg 804af69d88dSmrg pipe_resource_reference(&tmp, NULL); 805af69d88dSmrg} 806af69d88dSmrg 807af69d88dSmrgstatic void r300_blit(struct pipe_context *pipe, 808af69d88dSmrg const struct pipe_blit_info *blit) 809af69d88dSmrg{ 810af69d88dSmrg struct r300_context *r300 = r300_context(pipe); 811af69d88dSmrg struct pipe_framebuffer_state *fb = 812af69d88dSmrg (struct pipe_framebuffer_state*)r300->fb_state.state; 813af69d88dSmrg struct pipe_blit_info info = *blit; 814af69d88dSmrg 81501e04c3fSmrg /* The driver supports sRGB textures but not framebuffers. Blitting 81601e04c3fSmrg * from sRGB to sRGB should be the same as blitting from linear 81701e04c3fSmrg * to linear, so use that, This avoids incorrect linearization. 81801e04c3fSmrg */ 81901e04c3fSmrg if (util_format_is_srgb(info.src.format)) { 82001e04c3fSmrg info.src.format = util_format_linear(info.src.format); 82101e04c3fSmrg info.dst.format = util_format_linear(info.dst.format); 82201e04c3fSmrg } 82301e04c3fSmrg 824af69d88dSmrg /* MSAA resolve. */ 825af69d88dSmrg if (info.src.resource->nr_samples > 1 && 826af69d88dSmrg !util_format_is_depth_or_stencil(info.src.resource->format)) { 827af69d88dSmrg r300_msaa_resolve(pipe, &info); 828af69d88dSmrg return; 829af69d88dSmrg } 830af69d88dSmrg 831af69d88dSmrg /* Can't read MSAA textures. */ 832af69d88dSmrg if (info.src.resource->nr_samples > 1) { 833af69d88dSmrg return; 834af69d88dSmrg } 835af69d88dSmrg 836af69d88dSmrg /* Blit a combined depth-stencil resource as color. 837af69d88dSmrg * S8Z24 is the only supported stencil format. */ 838af69d88dSmrg if ((info.mask & PIPE_MASK_S) && 839af69d88dSmrg info.src.format == PIPE_FORMAT_S8_UINT_Z24_UNORM && 840af69d88dSmrg info.dst.format == PIPE_FORMAT_S8_UINT_Z24_UNORM) { 841af69d88dSmrg if (info.dst.resource->nr_samples > 1) { 842af69d88dSmrg /* Cannot do that with MSAA buffers. */ 843af69d88dSmrg info.mask &= ~PIPE_MASK_S; 844af69d88dSmrg if (!(info.mask & PIPE_MASK_Z)) { 845af69d88dSmrg return; 846af69d88dSmrg } 847af69d88dSmrg } else { 848af69d88dSmrg /* Single-sample buffer. */ 849af69d88dSmrg info.src.format = PIPE_FORMAT_B8G8R8A8_UNORM; 850af69d88dSmrg info.dst.format = PIPE_FORMAT_B8G8R8A8_UNORM; 851af69d88dSmrg if (info.mask & PIPE_MASK_Z) { 852af69d88dSmrg info.mask = PIPE_MASK_RGBA; /* depth+stencil */ 853af69d88dSmrg } else { 854af69d88dSmrg info.mask = PIPE_MASK_B; /* stencil only */ 855af69d88dSmrg } 856af69d88dSmrg } 857af69d88dSmrg } 858af69d88dSmrg 859af69d88dSmrg /* Decompress ZMASK. */ 860af69d88dSmrg if (r300->zmask_in_use && !r300->locked_zbuffer) { 861af69d88dSmrg if (fb->zsbuf->texture == info.src.resource || 862af69d88dSmrg fb->zsbuf->texture == info.dst.resource) { 863af69d88dSmrg r300_decompress_zmask(r300); 864af69d88dSmrg } 865af69d88dSmrg } 866af69d88dSmrg 867af69d88dSmrg r300_blitter_begin(r300, R300_BLIT | 868af69d88dSmrg (info.render_condition_enable ? 0 : R300_IGNORE_RENDER_COND)); 869af69d88dSmrg util_blitter_blit(r300->blitter, &info); 870af69d88dSmrg r300_blitter_end(r300); 871af69d88dSmrg} 872af69d88dSmrg 873af69d88dSmrgstatic void r300_flush_resource(struct pipe_context *ctx, 874af69d88dSmrg struct pipe_resource *resource) 875af69d88dSmrg{ 876cdc920a0Smrg} 877cdc920a0Smrg 8783464ebd5Sriastradhvoid r300_init_blit_functions(struct r300_context *r300) 879cdc920a0Smrg{ 8803464ebd5Sriastradh r300->context.clear = r300_clear; 8813464ebd5Sriastradh r300->context.clear_render_target = r300_clear_render_target; 8823464ebd5Sriastradh r300->context.clear_depth_stencil = r300_clear_depth_stencil; 8833464ebd5Sriastradh r300->context.resource_copy_region = r300_resource_copy_region; 884af69d88dSmrg r300->context.blit = r300_blit; 885af69d88dSmrg r300->context.flush_resource = r300_flush_resource; 886cdc920a0Smrg} 887