static void update_dst_buf_vars(struct i915_context *i915) { struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0]; struct pipe_surface *depth_surface = i915->framebuffer.zsbuf; uint32_t dst_buf_vars, cformat, zformat; uint32_t early_z = 0; uint32_t fixup = 0; int need_fixup; if (cbuf_surface) cformat = cbuf_surface->format; else cformat = PIPE_FORMAT_B8G8R8A8_UNORM; /* arbitrary */ cformat = translate_format(cformat); if (depth_surface) { struct i915_texture *tex = i915_texture(depth_surface->texture); struct i915_screen *is = i915_screen(i915->base.screen); zformat = translate_depth_format(depth_surface->format); if (is->is_i945 && tex->tiling != I915_TILE_NONE && !i915->fs->info.writes_z) early_z = CLASSIC_EARLY_DEPTH; } else zformat = 0; dst_buf_vars = DSTORG_HORT_BIAS(0x8) | /* .5 */ DSTORG_VERT_BIAS(0x8) | /* .5 */ LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL | cformat | zformat | early_z; if (i915->current.dst_buf_vars != dst_buf_vars) { if (early_z != (i915->current.dst_buf_vars & CLASSIC_EARLY_DEPTH)) i915_set_flush_dirty(i915, I915_PIPELINE_FLUSH); i915->current.dst_buf_vars = dst_buf_vars; i915->static_dirty |= I915_DST_VARS; i915->hardware_dirty |= I915_HW_STATIC; } need_fixup = need_target_fixup(cbuf_surface, &fixup); if (i915->current.target_fixup_format != need_fixup || i915->current.fixup_swizzle != fixup) { i915->current.target_fixup_format = need_fixup; i915->current.fixup_swizzle = fixup; /* we also send a new program to make sure the fixup for RGBA surfaces happens */ i915->hardware_dirty |= I915_HW_PROGRAM; } }
/* Push the state into the sarea and/or texture memory. */ void i915_emit_hardware_state(struct i915_context *i915 ) { /* XXX: there must be an easier way */ const unsigned dwords = ( 14 + 7 + I915_MAX_DYNAMIC + 8 + 2 + I915_TEX_UNITS*3 + 2 + I915_TEX_UNITS*3 + 2 + I915_MAX_CONSTANT*4 + #if 0 i915->current.program_len + #else i915->fs->program_len + #endif 6 ) * 3/2; /* plus 50% margin */ const unsigned relocs = ( I915_TEX_UNITS + 3 ) * 3/2; /* plus 50% margin */ #if 0 debug_printf("i915_emit_hardware_state: %d dwords, %d relocs\n", dwords, relocs); #endif if(!BEGIN_BATCH(dwords, relocs)) { FLUSH_BATCH(NULL); assert(BEGIN_BATCH(dwords, relocs)); } /* 14 dwords, 0 relocs */ if (i915->hardware_dirty & I915_HW_INVARIENT) { OUT_BATCH(_3DSTATE_AA_CMD | AA_LINE_ECAAR_WIDTH_ENABLE | AA_LINE_ECAAR_WIDTH_1_0 | AA_LINE_REGION_WIDTH_ENABLE | AA_LINE_REGION_WIDTH_1_0); OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD); OUT_BATCH(0); OUT_BATCH(_3DSTATE_DFLT_SPEC_CMD); OUT_BATCH(0); OUT_BATCH(_3DSTATE_DFLT_Z_CMD); OUT_BATCH(0); OUT_BATCH(_3DSTATE_COORD_SET_BINDINGS | CSB_TCB(0, 0) | CSB_TCB(1, 1) | CSB_TCB(2, 2) | CSB_TCB(3, 3) | CSB_TCB(4, 4) | CSB_TCB(5, 5) | CSB_TCB(6, 6) | CSB_TCB(7, 7)); OUT_BATCH(_3DSTATE_RASTER_RULES_CMD | ENABLE_POINT_RASTER_RULE | OGL_POINT_RASTER_RULE | ENABLE_LINE_STRIP_PROVOKE_VRTX | ENABLE_TRI_FAN_PROVOKE_VRTX | LINE_STRIP_PROVOKE_VRTX(1) | TRI_FAN_PROVOKE_VRTX(2) | ENABLE_TEXKILL_3D_4D | TEXKILL_4D); /* Need to initialize this to zero. */ OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(3) | (0)); OUT_BATCH(0); OUT_BATCH(_3DSTATE_DEPTH_SUBRECT_DISABLE); /* disable indirect state for now */ OUT_BATCH(_3DSTATE_LOAD_INDIRECT | 0); OUT_BATCH(0); } /* 7 dwords, 1 relocs */ if (i915->hardware_dirty & I915_HW_IMMEDIATE) { OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 | I1_LOAD_S(0) | I1_LOAD_S(1) | I1_LOAD_S(2) | I1_LOAD_S(4) | I1_LOAD_S(5) | I1_LOAD_S(6) | (5)); if(i915->vbo) OUT_RELOC(i915->vbo, I915_BUFFER_ACCESS_READ, i915->current.immediate[I915_IMMEDIATE_S0]); else /* FIXME: we should not do this */ OUT_BATCH(0); OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S1]); OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S2]); OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S4]); OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S5]); OUT_BATCH(i915->current.immediate[I915_IMMEDIATE_S6]); } /* I915_MAX_DYNAMIC dwords, 0 relocs */ if (i915->hardware_dirty & I915_HW_DYNAMIC) { int i; for (i = 0; i < I915_MAX_DYNAMIC; i++) { OUT_BATCH(i915->current.dynamic[i]); } } /* 8 dwords, 2 relocs */ if (i915->hardware_dirty & I915_HW_STATIC) { struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0]; struct pipe_surface *depth_surface = i915->framebuffer.zsbuf; if (cbuf_surface) { unsigned cpitch = cbuf_surface->stride; unsigned ctile = BUF_3D_USE_FENCE; if (cbuf_surface->texture && ((struct i915_texture*)(cbuf_surface->texture))->tiled) { ctile = BUF_3D_TILED_SURFACE; } OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_PITCH(cpitch) | /* pitch in bytes */ ctile); OUT_RELOC(cbuf_surface->buffer, I915_BUFFER_ACCESS_WRITE, cbuf_surface->offset); } /* What happens if no zbuf?? */ if (depth_surface) { unsigned zpitch = depth_surface->stride; unsigned ztile = BUF_3D_USE_FENCE; if (depth_surface->texture && ((struct i915_texture*)(depth_surface->texture))->tiled) { ztile = BUF_3D_TILED_SURFACE; } OUT_BATCH(_3DSTATE_BUF_INFO_CMD); OUT_BATCH(BUF_3D_ID_DEPTH | BUF_3D_PITCH(zpitch) | /* pitch in bytes */ ztile); OUT_RELOC(depth_surface->buffer, I915_BUFFER_ACCESS_WRITE, depth_surface->offset); } { unsigned cformat, zformat = 0; if (cbuf_surface) cformat = cbuf_surface->format; else cformat = PIPE_FORMAT_A8R8G8B8_UNORM; /* arbitrary */ cformat = translate_format(cformat); if (depth_surface) zformat = translate_depth_format( i915->framebuffer.zsbuf->format ); OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD); OUT_BATCH(DSTORG_HORT_BIAS(0x8) | /* .5 */ DSTORG_VERT_BIAS(0x8) | /* .5 */ LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL | cformat | zformat ); } } #if 01 /* texture images */ /* 2 + I915_TEX_UNITS*3 dwords, I915_TEX_UNITS relocs */ if (i915->hardware_dirty & (I915_HW_MAP | I915_HW_SAMPLER)) { const uint nr = i915->current.sampler_enable_nr; if (nr) { const uint enabled = i915->current.sampler_enable_flags; uint unit; uint count = 0; OUT_BATCH(_3DSTATE_MAP_STATE | (3 * nr)); OUT_BATCH(enabled); for (unit = 0; unit < I915_TEX_UNITS; unit++) { if (enabled & (1 << unit)) { struct pipe_buffer *buf = i915->texture[unit]->buffer; uint offset = 0; assert(buf); count++; OUT_RELOC(buf, I915_BUFFER_ACCESS_READ, offset); OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */ OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */ } } assert(count == nr); } } #endif #if 01 /* samplers */ /* 2 + I915_TEX_UNITS*3 dwords, 0 relocs */ if (i915->hardware_dirty & I915_HW_SAMPLER) { if (i915->current.sampler_enable_nr) { int i; OUT_BATCH( _3DSTATE_SAMPLER_STATE | (3 * i915->current.sampler_enable_nr) ); OUT_BATCH( i915->current.sampler_enable_flags ); for (i = 0; i < I915_TEX_UNITS; i++) { if (i915->current.sampler_enable_flags & (1<<i)) { OUT_BATCH( i915->current.sampler[i][0] ); OUT_BATCH( i915->current.sampler[i][1] ); OUT_BATCH( i915->current.sampler[i][2] ); } } } } #endif /* constants */ /* 2 + I915_MAX_CONSTANT*4 dwords, 0 relocs */ if (i915->hardware_dirty & I915_HW_PROGRAM) { /* Collate the user-defined constants with the fragment shader's * immediates according to the constant_flags[] array. */ const uint nr = i915->fs->num_constants; if (nr) { uint i; OUT_BATCH( _3DSTATE_PIXEL_SHADER_CONSTANTS | (nr * 4) ); OUT_BATCH( (1 << (nr - 1)) | ((1 << (nr - 1)) - 1) ); for (i = 0; i < nr; i++) { const uint *c; if (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER) { /* grab user-defined constant */ c = (uint *) i915->current.constants[PIPE_SHADER_FRAGMENT][i]; } else { /* emit program constant */ c = (uint *) i915->fs->constants[i]; } #if 0 /* debug */ { float *f = (float *) c; printf("Const %2d: %f %f %f %f %s\n", i, f[0], f[1], f[2], f[3], (i915->fs->constant_flags[i] == I915_CONSTFLAG_USER ? "user" : "immediate")); } #endif OUT_BATCH(*c++); OUT_BATCH(*c++); OUT_BATCH(*c++); OUT_BATCH(*c++); } } } /* Fragment program */ /* i915->current.program_len dwords, 0 relocs */ if (i915->hardware_dirty & I915_HW_PROGRAM) { uint i; /* we should always have, at least, a pass-through program */ assert(i915->fs->program_len > 0); for (i = 0; i < i915->fs->program_len; i++) { OUT_BATCH(i915->fs->program[i]); } } /* drawing surface size */ /* 6 dwords, 0 relocs */ { uint w, h; boolean k = framebuffer_size(&i915->framebuffer, &w, &h); (void)k; assert(k); OUT_BATCH(_3DSTATE_DRAW_RECT_CMD); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(((w - 1) & 0xffff) | ((h - 1) << 16)); OUT_BATCH(0); OUT_BATCH(0); } i915->hardware_dirty = 0; }
static void etna_set_framebuffer_state(struct pipe_context *pctx, const struct pipe_framebuffer_state *sv) { struct etna_context *ctx = etna_context(pctx); struct compiled_framebuffer_state *cs = &ctx->framebuffer; int nr_samples_color = -1; int nr_samples_depth = -1; /* Set up TS as well. Warning: this state is used by both the RS and PE */ uint32_t ts_mem_config = 0; if (sv->nr_cbufs > 0) { /* at least one color buffer? */ struct etna_surface *cbuf = etna_surface(sv->cbufs[0]); struct etna_resource *res = etna_resource(cbuf->base.texture); bool color_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; assert(res->layout & ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ etna_update_render_resource(pctx, cbuf->base.texture); pipe_surface_reference(&cs->cbuf, &cbuf->base); cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_FORMAT(translate_rs_format(cbuf->base.format)) | VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK | VIVS_PE_COLOR_FORMAT_OVERWRITE | COND(color_supertiled, VIVS_PE_COLOR_FORMAT_SUPER_TILED) | COND(color_supertiled && ctx->specs.halti >= 5, VIVS_PE_COLOR_FORMAT_SUPER_TILED_NEW); /* VIVS_PE_COLOR_FORMAT_COMPONENTS() and * VIVS_PE_COLOR_FORMAT_OVERWRITE comes from blend_state * but only if we set the bits above. */ /* merged with depth_stencil_alpha */ if ((cbuf->surf.offset & 63) || (((cbuf->surf.stride * 4) & 63) && cbuf->surf.height > 4)) { /* XXX Must make temporary surface here. * Need the same mechanism on gc2000 when we want to do mipmap * generation by * rendering to levels > 1 due to multitiled / tiled conversion. */ BUG("Alignment error, trying to render to offset %08x with tile " "stride %i", cbuf->surf.offset, cbuf->surf.stride * 4); } if (ctx->specs.pixel_pipes == 1) { cs->PE_COLOR_ADDR = cbuf->reloc[0]; cs->PE_COLOR_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } else { /* Rendered textures must always be multi-tiled, or single-buffer mode must be supported */ assert((res->layout & ETNA_LAYOUT_BIT_MULTI) || ctx->specs.single_buffer); for (int i = 0; i < ctx->specs.pixel_pipes; i++) { cs->PE_PIPE_COLOR_ADDR[i] = cbuf->reloc[i]; cs->PE_PIPE_COLOR_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } } cs->PE_COLOR_STRIDE = cbuf->surf.stride; if (cbuf->surf.ts_size) { cs->TS_COLOR_CLEAR_VALUE = cbuf->level->clear_value; cs->TS_COLOR_STATUS_BASE = cbuf->ts_reloc; cs->TS_COLOR_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; cs->TS_COLOR_SURFACE_BASE = cbuf->reloc[0]; cs->TS_COLOR_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } /* MSAA */ if (cbuf->base.texture->nr_samples > 1) ts_mem_config |= VIVS_TS_MEM_CONFIG_COLOR_COMPRESSION | translate_msaa_format(cbuf->base.format); nr_samples_color = cbuf->base.texture->nr_samples; } else { pipe_surface_reference(&cs->cbuf, NULL); /* Clearing VIVS_PE_COLOR_FORMAT_COMPONENTS__MASK and * VIVS_PE_COLOR_FORMAT_OVERWRITE prevents us from overwriting the * color target */ cs->PE_COLOR_FORMAT = VIVS_PE_COLOR_FORMAT_OVERWRITE; cs->PE_COLOR_STRIDE = 0; cs->TS_COLOR_STATUS_BASE.bo = NULL; cs->TS_COLOR_SURFACE_BASE.bo = NULL; for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++) cs->PE_PIPE_COLOR_ADDR[i].bo = NULL; } if (sv->zsbuf != NULL) { struct etna_surface *zsbuf = etna_surface(sv->zsbuf); struct etna_resource *res = etna_resource(zsbuf->base.texture); etna_update_render_resource(pctx, zsbuf->base.texture); pipe_surface_reference(&cs->zsbuf, &zsbuf->base); assert(res->layout &ETNA_LAYOUT_BIT_TILE); /* Cannot render to linear surfaces */ uint32_t depth_format = translate_depth_format(zsbuf->base.format); unsigned depth_bits = depth_format == VIVS_PE_DEPTH_CONFIG_DEPTH_FORMAT_D16 ? 16 : 24; bool depth_supertiled = (res->layout & ETNA_LAYOUT_BIT_SUPER) != 0; cs->PE_DEPTH_CONFIG = depth_format | COND(depth_supertiled, VIVS_PE_DEPTH_CONFIG_SUPER_TILED) | VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_Z | COND(ctx->specs.halti >= 5, VIVS_PE_DEPTH_CONFIG_DISABLE_ZS) /* Needs to be enabled on GC7000, otherwise depth writes hang w/ TS - apparently it does something else now */ ; /* VIVS_PE_DEPTH_CONFIG_ONLY_DEPTH */ /* merged with depth_stencil_alpha */ if (ctx->specs.pixel_pipes == 1) { cs->PE_DEPTH_ADDR = zsbuf->reloc[0]; cs->PE_DEPTH_ADDR.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } else { for (int i = 0; i < ctx->specs.pixel_pipes; i++) { cs->PE_PIPE_DEPTH_ADDR[i] = zsbuf->reloc[i]; cs->PE_PIPE_DEPTH_ADDR[i].flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } } cs->PE_DEPTH_STRIDE = zsbuf->surf.stride; cs->PE_HDEPTH_CONTROL = VIVS_PE_HDEPTH_CONTROL_FORMAT_DISABLED; cs->PE_DEPTH_NORMALIZE = fui(exp2f(depth_bits) - 1.0f); if (zsbuf->surf.ts_size) { cs->TS_DEPTH_CLEAR_VALUE = zsbuf->level->clear_value; cs->TS_DEPTH_STATUS_BASE = zsbuf->ts_reloc; cs->TS_DEPTH_STATUS_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; cs->TS_DEPTH_SURFACE_BASE = zsbuf->reloc[0]; cs->TS_DEPTH_SURFACE_BASE.flags = ETNA_RELOC_READ | ETNA_RELOC_WRITE; } ts_mem_config |= COND(depth_bits == 16, VIVS_TS_MEM_CONFIG_DEPTH_16BPP); /* MSAA */ if (zsbuf->base.texture->nr_samples > 1) /* XXX VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION; * Disable without MSAA for now, as it causes corruption in glquake. */ ts_mem_config |= VIVS_TS_MEM_CONFIG_DEPTH_COMPRESSION; nr_samples_depth = zsbuf->base.texture->nr_samples; } else { pipe_surface_reference(&cs->zsbuf, NULL); cs->PE_DEPTH_CONFIG = VIVS_PE_DEPTH_CONFIG_DEPTH_MODE_NONE; cs->PE_DEPTH_ADDR.bo = NULL; cs->PE_DEPTH_STRIDE = 0; cs->TS_DEPTH_STATUS_BASE.bo = NULL; cs->TS_DEPTH_SURFACE_BASE.bo = NULL; for (int i = 0; i < ETNA_MAX_PIXELPIPES; i++) cs->PE_PIPE_DEPTH_ADDR[i].bo = NULL; } /* MSAA setup */ if (nr_samples_depth != -1 && nr_samples_color != -1 && nr_samples_depth != nr_samples_color) { BUG("Number of samples in color and depth texture must match (%i and %i respectively)", nr_samples_color, nr_samples_depth); } switch (MAX2(nr_samples_depth, nr_samples_color)) { case 0: case 1: /* Are 0 and 1 samples allowed? */ cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_NONE; cs->msaa_mode = false; break; case 2: cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_2X; cs->msaa_mode = true; /* Add input to PS */ cs->RA_MULTISAMPLE_UNK00E04 = 0x0; cs->RA_MULTISAMPLE_UNK00E10[0] = 0x0000aa22; cs->RA_CENTROID_TABLE[0] = 0x66aa2288; cs->RA_CENTROID_TABLE[1] = 0x88558800; cs->RA_CENTROID_TABLE[2] = 0x88881100; cs->RA_CENTROID_TABLE[3] = 0x33888800; break; case 4: cs->GL_MULTI_SAMPLE_CONFIG = VIVS_GL_MULTI_SAMPLE_CONFIG_MSAA_SAMPLES_4X; cs->msaa_mode = true; /* Add input to PS */ cs->RA_MULTISAMPLE_UNK00E04 = 0x0; cs->RA_MULTISAMPLE_UNK00E10[0] = 0xeaa26e26; cs->RA_MULTISAMPLE_UNK00E10[1] = 0xe6ae622a; cs->RA_MULTISAMPLE_UNK00E10[2] = 0xaaa22a22; cs->RA_CENTROID_TABLE[0] = 0x4a6e2688; cs->RA_CENTROID_TABLE[1] = 0x888888a2; cs->RA_CENTROID_TABLE[2] = 0x888888ea; cs->RA_CENTROID_TABLE[3] = 0x888888c6; cs->RA_CENTROID_TABLE[4] = 0x46622a88; cs->RA_CENTROID_TABLE[5] = 0x888888ae; cs->RA_CENTROID_TABLE[6] = 0x888888e6; cs->RA_CENTROID_TABLE[7] = 0x888888ca; cs->RA_CENTROID_TABLE[8] = 0x262a2288; cs->RA_CENTROID_TABLE[9] = 0x886688a2; cs->RA_CENTROID_TABLE[10] = 0x888866aa; cs->RA_CENTROID_TABLE[11] = 0x668888a6; break; } /* Scissor setup */ cs->SE_SCISSOR_LEFT = 0; /* affected by rasterizer and scissor state as well */ cs->SE_SCISSOR_TOP = 0; cs->SE_SCISSOR_RIGHT = (sv->width << 16) + ETNA_SE_SCISSOR_MARGIN_RIGHT; cs->SE_SCISSOR_BOTTOM = (sv->height << 16) + ETNA_SE_SCISSOR_MARGIN_BOTTOM; cs->SE_CLIP_RIGHT = (sv->width << 16) + ETNA_SE_CLIP_MARGIN_RIGHT; cs->SE_CLIP_BOTTOM = (sv->height << 16) + ETNA_SE_CLIP_MARGIN_BOTTOM; cs->TS_MEM_CONFIG = ts_mem_config; /* Single buffer setup. There is only one switch for this, not a separate * one per color buffer / depth buffer. To keep the logic simple always use * single buffer when this feature is available. */ cs->PE_LOGIC_OP = VIVS_PE_LOGIC_OP_SINGLE_BUFFER(ctx->specs.single_buffer ? 2 : 0); ctx->framebuffer_s = *sv; /* keep copy of original structure */ ctx->dirty |= ETNA_DIRTY_FRAMEBUFFER | ETNA_DIRTY_DERIVE_TS; }
static boolean etna_screen_is_format_supported(struct pipe_screen *pscreen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, unsigned usage) { struct etna_screen *screen = etna_screen(pscreen); unsigned allowed = 0; if (target != PIPE_BUFFER && target != PIPE_TEXTURE_1D && target != PIPE_TEXTURE_2D && target != PIPE_TEXTURE_3D && target != PIPE_TEXTURE_CUBE && target != PIPE_TEXTURE_RECT) return FALSE; if (usage & PIPE_BIND_RENDER_TARGET) { /* If render target, must be RS-supported format that is not rb swapped. * Exposing rb swapped (or other swizzled) formats for rendering would * involve swizzing in the pixel shader. */ if (translate_rs_format(format) != ETNA_NO_MATCH && !translate_rs_format_rb_swap(format)) { /* Validate MSAA; number of samples must be allowed, and render target * must have MSAA'able format. */ if (sample_count > 1) { if (translate_samples_to_xyscale(sample_count, NULL, NULL, NULL) && translate_msaa_format(format) != ETNA_NO_MATCH) { allowed |= PIPE_BIND_RENDER_TARGET; } } else { allowed |= PIPE_BIND_RENDER_TARGET; } } } if (usage & PIPE_BIND_DEPTH_STENCIL) { if (translate_depth_format(format) != ETNA_NO_MATCH) allowed |= PIPE_BIND_DEPTH_STENCIL; } if (usage & PIPE_BIND_SAMPLER_VIEW) { uint32_t fmt = translate_texture_format(format); if (!gpu_supports_texure_format(screen, fmt)) fmt = ETNA_NO_MATCH; if (sample_count < 2 && fmt != ETNA_NO_MATCH) allowed |= PIPE_BIND_SAMPLER_VIEW; } if (usage & PIPE_BIND_VERTEX_BUFFER) { if (translate_vertex_format_type(format) != ETNA_NO_MATCH) allowed |= PIPE_BIND_VERTEX_BUFFER; } if (usage & PIPE_BIND_INDEX_BUFFER) { /* must be supported index format */ if (format == PIPE_FORMAT_I8_UINT || format == PIPE_FORMAT_I16_UINT || (format == PIPE_FORMAT_I32_UINT && VIV_FEATURE(screen, chipFeatures, 32_BIT_INDICES))) { allowed |= PIPE_BIND_INDEX_BUFFER; } } /* Always allowed */ allowed |= usage & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED); if (usage != allowed) { DBG("not supported: format=%s, target=%d, sample_count=%d, " "usage=%x, allowed=%x", util_format_name(format), target, sample_count, usage, allowed); } return usage == allowed; }
static boolean etna_screen_is_format_supported( struct pipe_screen *screen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, unsigned usage) { struct etna_screen *priv = etna_screen(screen); unsigned allowed = 0; if (target >= PIPE_MAX_TEXTURE_TYPES) { return FALSE; } if (usage & PIPE_BIND_RENDER_TARGET) { /* if render target, must be RS-supported format */ if(translate_rt_format(format, true) != ETNA_NO_MATCH) { /* Validate MSAA; number of samples must be allowed, and render target must have * MSAA'able format. */ if(sample_count > 1) { if(translate_samples_to_xyscale(sample_count, NULL, NULL, NULL) && translate_msaa_format(format, true) != ETNA_NO_MATCH) { allowed |= PIPE_BIND_RENDER_TARGET; } } else { allowed |= PIPE_BIND_RENDER_TARGET; } } } if (usage & PIPE_BIND_DEPTH_STENCIL) { /* must be supported depth format */ if(translate_depth_format(format, true) != ETNA_NO_MATCH) { allowed |= PIPE_BIND_DEPTH_STENCIL; } } if (usage & PIPE_BIND_SAMPLER_VIEW) { /* must be supported texture format */ if(sample_count < 2 && translate_texture_format(format, true) != ETNA_NO_MATCH) { allowed |= PIPE_BIND_SAMPLER_VIEW; } } if (usage & PIPE_BIND_VERTEX_BUFFER) { /* must be supported vertex format */ if(translate_vertex_format_type(format, true) == ETNA_NO_MATCH) { allowed |= PIPE_BIND_VERTEX_BUFFER; } } if (usage & PIPE_BIND_INDEX_BUFFER) { /* must be supported index format */ if(format == PIPE_FORMAT_I8_UINT || format == PIPE_FORMAT_I16_UINT || (format == PIPE_FORMAT_I32_UINT && VIV_FEATURE(priv->dev, chipFeatures, 32_BIT_INDICES))) { allowed |= PIPE_BIND_INDEX_BUFFER; } } /* Always allowed */ allowed |= usage & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_TRANSFER_READ | PIPE_BIND_TRANSFER_WRITE); return usage == allowed; }