void util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height) { unsigned x, y; float p[3]; for(y = 0; y < height; y += 1) { uint8_t *dst = dst_row; const uint8_t *src = src_row; for(x = 0; x < width; x += 1) { uint32_t value = *(const uint32_t *)src; #ifdef PIPE_ARCH_BIG_ENDIAN value = util_bswap32(value); #endif rgb9e5_to_float3(value, p); dst[0] = float_to_ubyte(p[0]); /* r */ dst[1] = float_to_ubyte(p[1]); /* g */ dst[2] = float_to_ubyte(p[2]); /* b */ dst[3] = 255; /* a */ src += 4; dst += 4; } src_row += src_stride; dst_row += dst_stride/sizeof(*dst_row); } }
static inline void util_format_dxtn_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src, unsigned src_stride, unsigned width, unsigned height, enum util_format_dxtn format, unsigned block_size, boolean srgb) { unsigned x, y, i, j, k; for(y = 0; y < height; y += 4) { uint8_t *dst = dst_row; for(x = 0; x < width; x += 4) { uint8_t tmp[4][4][4]; for(j = 0; j < 4; ++j) { for(i = 0; i < 4; ++i) { float src_tmp; for(k = 0; k < 3; ++k) { src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]; if (srgb) { tmp[j][i][k] = util_format_linear_float_to_srgb_8unorm(src_tmp); } else { tmp[j][i][k] = float_to_ubyte(src_tmp); } } /* for sake of simplicity there's an unneeded 4th component for dxt1_rgb */ src_tmp = src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + 3]; tmp[j][i][3] = float_to_ubyte(src_tmp); } } util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], format, dst, 0); dst += block_size; } dst_row += 4*dst_stride/sizeof(*dst_row); } }
uint32_t Color::as_uint32() const { return static_cast<uint32_t>((( float_to_ubyte(alpha) << 24) | (float_to_ubyte(blue) << 16) | (float_to_ubyte(green) << 8) | float_to_ubyte(red))); }
void debug_dump_float_rgba_bmp(const char *filename, unsigned width, unsigned height, float *rgba, unsigned stride) { #ifndef PIPE_SUBSYSTEM_WINDOWS_MINIPORT struct os_stream *stream; struct bmp_file_header bmfh; struct bmp_info_header bmih; unsigned x, y; if(!rgba) goto error1; bmfh.bfType = 0x4d42; bmfh.bfSize = 14 + 40 + height*width*4; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = 14 + 40; bmih.biSize = 40; bmih.biWidth = width; bmih.biHeight = height; bmih.biPlanes = 1; bmih.biBitCount = 32; bmih.biCompression = 0; bmih.biSizeImage = height*width*4; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; stream = os_file_stream_create(filename); if(!stream) goto error1; os_stream_write(stream, &bmfh, 14); os_stream_write(stream, &bmih, 40); y = height; while(y--) { float *ptr = rgba + (stride * y * 4); for(x = 0; x < width; ++x) { struct bmp_rgb_quad pixel; pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]); pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]); pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]); pixel.rgbAlpha = 255; os_stream_write(stream, &pixel, 4); } } os_stream_close(stream); error1: ; #endif }
void debug_dump_float_rgba_bmp(const char *filename, unsigned width, unsigned height, float *rgba, unsigned stride) { FILE *stream; struct bmp_file_header bmfh; struct bmp_info_header bmih; unsigned x, y; if(!rgba) goto error1; bmfh.bfType = 0x4d42; bmfh.bfSize = 14 + 40 + height*width*4; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = 14 + 40; bmih.biSize = 40; bmih.biWidth = width; bmih.biHeight = height; bmih.biPlanes = 1; bmih.biBitCount = 32; bmih.biCompression = 0; bmih.biSizeImage = height*width*4; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; stream = fopen(filename, "wb"); if(!stream) goto error1; fwrite(&bmfh, 14, 1, stream); fwrite(&bmih, 40, 1, stream); y = height; while(y--) { float *ptr = rgba + (stride * y * 4); for(x = 0; x < width; ++x) { struct bmp_rgb_quad pixel; pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]); pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]); pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]); pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]); fwrite(&pixel, 1, 4, stream); } } fclose(stream); error1: ; }
static void * nv30_sampler_state_create(struct pipe_context *pipe, const struct pipe_sampler_state *cso) { struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; struct nv30_sampler_state *so; const float max_lod = 15.0 + (255.0 / 256.0); so = MALLOC_STRUCT(nv30_sampler_state); if (!so) return NULL; so->pipe = *cso; so->fmt = 0; so->wrap = (wrap_mode(cso->wrap_s) << NV30_3D_TEX_WRAP_S__SHIFT) | (wrap_mode(cso->wrap_t) << NV30_3D_TEX_WRAP_T__SHIFT) | (wrap_mode(cso->wrap_r) << NV30_3D_TEX_WRAP_R__SHIFT); so->en = 0; so->wrap |= compare_mode(cso); so->filt = filter_mode(cso) | 0x00002000; so->bcol = (float_to_ubyte(cso->border_color.f[3]) << 24) | (float_to_ubyte(cso->border_color.f[0]) << 16) | (float_to_ubyte(cso->border_color.f[1]) << 8) | (float_to_ubyte(cso->border_color.f[2]) << 0); if (eng3d->oclass >= NV40_3D_CLASS) { unsigned aniso = cso->max_anisotropy; if (!cso->normalized_coords) so->fmt |= NV40_3D_TEX_FORMAT_RECT; if (aniso > 1) { if (aniso >= 16) so->en |= NV40_3D_TEX_ENABLE_ANISO_16X; else if (aniso >= 12) so->en |= NV40_3D_TEX_ENABLE_ANISO_12X; else if (aniso >= 10) so->en |= NV40_3D_TEX_ENABLE_ANISO_10X; else if (aniso >= 8) so->en |= NV40_3D_TEX_ENABLE_ANISO_8X; else if (aniso >= 6) so->en |= NV40_3D_TEX_ENABLE_ANISO_6X; else if (aniso >= 4) so->en |= NV40_3D_TEX_ENABLE_ANISO_4X; else so->en |= NV40_3D_TEX_ENABLE_ANISO_2X; so->wrap |= nv30_context(pipe)->config.aniso; } } else { so->en |= NV30_3D_TEX_ENABLE_ENABLE; if (cso->max_anisotropy >= 8) so->en |= NV30_3D_TEX_ENABLE_ANISO_8X; else if (cso->max_anisotropy >= 4) so->en |= NV30_3D_TEX_ENABLE_ANISO_4X; else if (cso->max_anisotropy >= 2) so->en |= NV30_3D_TEX_ENABLE_ANISO_2X; } so->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; so->max_lod = (int)(CLAMP(cso->max_lod, 0.0, max_lod) * 256.0); so->min_lod = (int)(CLAMP(cso->min_lod, 0.0, max_lod) * 256.0); return so; }
static void * svga_create_sampler_state(struct pipe_context *pipe, const struct pipe_sampler_state *sampler) { struct svga_context *svga = svga_context(pipe); struct svga_sampler_state *cso = CALLOC_STRUCT( svga_sampler_state ); cso->mipfilter = translate_mip_filter(sampler->min_mip_filter); cso->magfilter = translate_img_filter( sampler->mag_img_filter ); cso->minfilter = translate_img_filter( sampler->min_img_filter ); cso->aniso_level = MAX2( (unsigned) sampler->max_anisotropy, 1 ); cso->lod_bias = sampler->lod_bias; cso->addressu = translate_wrap_mode(sampler->wrap_s); cso->addressv = translate_wrap_mode(sampler->wrap_t); cso->addressw = translate_wrap_mode(sampler->wrap_r); cso->normalized_coords = sampler->normalized_coords; cso->compare_mode = sampler->compare_mode; cso->compare_func = sampler->compare_func; { ubyte r = float_to_ubyte(sampler->border_color[0]); ubyte g = float_to_ubyte(sampler->border_color[1]); ubyte b = float_to_ubyte(sampler->border_color[2]); ubyte a = float_to_ubyte(sampler->border_color[3]); util_pack_color_ub( r, g, b, a, PIPE_FORMAT_B8G8R8A8_UNORM, &cso->bordercolor ); } /* No SVGA3D support for: * - min/max LOD clamping */ cso->min_lod = 0; cso->view_min_lod = MAX2(sampler->min_lod, 0); cso->view_max_lod = MAX2(sampler->max_lod, 0); /* Use min_mipmap */ if (svga->debug.use_min_mipmap) { if (cso->view_min_lod == cso->view_max_lod) { cso->min_lod = cso->view_min_lod; cso->view_min_lod = 0; cso->view_max_lod = 1000; /* Just a high number */ cso->mipfilter = SVGA3D_TEX_FILTER_NONE; } } SVGA_DBG(DEBUG_VIEWS, "min %u, view(min %u, max %u) lod, mipfilter %s\n", cso->min_lod, cso->view_min_lod, cso->view_max_lod, cso->mipfilter == SVGA3D_TEX_FILTER_NONE ? "SVGA3D_TEX_FILTER_NONE" : "SOMETHING"); return cso; }
void nvfx_state_blend_colour_validate(struct nvfx_context *nvfx) { struct nouveau_channel* chan = nvfx->screen->base.channel; struct nouveau_grobj *eng3d = nvfx->screen->eng3d; struct pipe_blend_color *bcol = &nvfx->blend_colour; BEGIN_RING(chan, eng3d, NV30_3D_BLEND_COLOR, 1); OUT_RING(chan, ((float_to_ubyte(bcol->color[3]) << 24) | (float_to_ubyte(bcol->color[0]) << 16) | (float_to_ubyte(bcol->color[1]) << 8) | (float_to_ubyte(bcol->color[2]) << 0))); }
void image_clear(struct vg_image *img, VGint x, VGint y, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); VGfloat *clear_colorf = ctx->state.vg.clear_color; VGubyte r, g, b ,a; VGint clear_colori; /* FIXME: this is very nasty */ r = float_to_ubyte(clear_colorf[0]); g = float_to_ubyte(clear_colorf[1]); b = float_to_ubyte(clear_colorf[2]); a = float_to_ubyte(clear_colorf[3]); clear_colori = r << 24 | g << 16 | b << 8 | a; image_cleari(img, clear_colori, x, y, width, height); }
static boolean nv40_state_blend_colour_validate(struct nv40_context *nv40) { struct nouveau_stateobj *so = so_new(2, 0); struct pipe_blend_color *bcol = &nv40->blend_colour; so_method(so, nv40->screen->curie, NV40TCL_BLEND_COLOR, 1); so_data (so, ((float_to_ubyte(bcol->color[3]) << 24) | (float_to_ubyte(bcol->color[0]) << 16) | (float_to_ubyte(bcol->color[1]) << 8) | (float_to_ubyte(bcol->color[2]) << 0))); so_ref(so, &nv40->state.hw[NV40_STATE_BCOL]); so_ref(NULL, &so); return TRUE; }
/** * Extract the needed fields from vertex_header and emit i915 dwords. * Recall that the vertices are constructed by the 'draw' module and * have a couple of slots at the beginning (1-dword header, 4-dword * clip pos) that we ignore here. */ static INLINE void emit_hw_vertex( struct i915_context *i915, const struct vertex_header *vertex) { const struct vertex_info *vinfo = &i915->current.vertex_info; uint i; uint count = 0; /* for debug/sanity */ assert(!i915->dirty); for (i = 0; i < vinfo->num_attribs; i++) { const uint j = vinfo->attrib[i].src_index; const float *attrib = vertex->data[j]; switch (vinfo->attrib[i].emit) { case EMIT_1F: OUT_BATCH( fui(attrib[0]) ); count++; break; case EMIT_2F: OUT_BATCH( fui(attrib[0]) ); OUT_BATCH( fui(attrib[1]) ); count += 2; break; case EMIT_3F: OUT_BATCH( fui(attrib[0]) ); OUT_BATCH( fui(attrib[1]) ); OUT_BATCH( fui(attrib[2]) ); count += 3; break; case EMIT_4F: OUT_BATCH( fui(attrib[0]) ); OUT_BATCH( fui(attrib[1]) ); OUT_BATCH( fui(attrib[2]) ); OUT_BATCH( fui(attrib[3]) ); count += 4; break; case EMIT_4UB: OUT_BATCH( pack_ub4(float_to_ubyte( attrib[0] ), float_to_ubyte( attrib[1] ), float_to_ubyte( attrib[2] ), float_to_ubyte( attrib[3] )) ); count += 1; break; case EMIT_4UB_BGRA: OUT_BATCH( pack_ub4(float_to_ubyte( attrib[2] ), float_to_ubyte( attrib[1] ), float_to_ubyte( attrib[0] ), float_to_ubyte( attrib[3] )) ); count += 1; break; default: assert(0); } } assert(count == vinfo->size); }
static void vc4_set_blend_color(struct pipe_context *pctx, const struct pipe_blend_color *blend_color) { struct vc4_context *vc4 = vc4_context(pctx); vc4->blend_color.f = *blend_color; for (int i = 0; i < 4; i++) vc4->blend_color.ub[i] = float_to_ubyte(blend_color->color[i]); vc4->dirty |= VC4_DIRTY_BLEND_COLOR; }
static void * nv40_depth_stencil_alpha_state_create(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *cso) { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_zsa_state *zsaso = CALLOC(1, sizeof(*zsaso)); struct nouveau_stateobj *so = so_new(32, 0); struct nouveau_grobj *curie = nv40->screen->curie; so_method(so, curie, NV40TCL_DEPTH_FUNC, 3); so_data (so, nvgl_comparison_op(cso->depth.func)); so_data (so, cso->depth.writemask ? 1 : 0); so_data (so, cso->depth.enabled ? 1 : 0); so_method(so, curie, NV40TCL_ALPHA_TEST_ENABLE, 3); so_data (so, cso->alpha.enabled ? 1 : 0); so_data (so, nvgl_comparison_op(cso->alpha.func)); so_data (so, float_to_ubyte(cso->alpha.ref_value)); if (cso->stencil[0].enabled) { so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 8); so_data (so, cso->stencil[0].enabled ? 1 : 0); so_data (so, cso->stencil[0].writemask); so_data (so, nvgl_comparison_op(cso->stencil[0].func)); so_data (so, cso->stencil[0].ref_value); so_data (so, cso->stencil[0].valuemask); so_data (so, nvgl_stencil_op(cso->stencil[0].fail_op)); so_data (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); so_data (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); } else { so_method(so, curie, NV40TCL_STENCIL_FRONT_ENABLE, 1); so_data (so, 0); } if (cso->stencil[1].enabled) { so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 8); so_data (so, cso->stencil[1].enabled ? 1 : 0); so_data (so, cso->stencil[1].writemask); so_data (so, nvgl_comparison_op(cso->stencil[1].func)); so_data (so, cso->stencil[1].ref_value); so_data (so, cso->stencil[1].valuemask); so_data (so, nvgl_stencil_op(cso->stencil[1].fail_op)); so_data (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); so_data (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); } else { so_method(so, curie, NV40TCL_STENCIL_BACK_ENABLE, 1); so_data (so, 0); } so_ref(so, &zsaso->so); so_ref(NULL, &so); zsaso->pipe = *cso; return (void *)zsaso; }
void util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off) { const unsigned bw = 4, bh = 4, bytes_per_block = 16; unsigned x, y, i, j; for(y = 0; y < height; y += bh) { uint8_t *dst = dst_row; for(x = 0; x < width; x += bw) { uint8_t tmp_r[4][4]; /* [bh][bw][comps] */ uint8_t tmp_g[4][4]; /* [bh][bw][comps] */ for(j = 0; j < bh; ++j) { for(i = 0; i < bw; ++i) { tmp_r[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]); tmp_g[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4 + chan2off]); } } u_format_unsigned_encode_rgtc_ubyte(dst, tmp_r, 4, 4); u_format_unsigned_encode_rgtc_ubyte(dst + 8, tmp_g, 4, 4); dst += bytes_per_block; } dst_row += dst_stride / sizeof(*dst_row); } }
static void create_bcc_state( struct brw_depth_stencil_state *zstencil, const struct pipe_depth_stencil_alpha_state *templ ) { if (templ->stencil[0].enabled) { zstencil->cc0.stencil_enable = 1; zstencil->cc0.stencil_func = brw_translate_compare_func(templ->stencil[0].func); zstencil->cc0.stencil_fail_op = translate_stencil_op(templ->stencil[0].fail_op); zstencil->cc0.stencil_pass_depth_fail_op = translate_stencil_op(templ->stencil[0].zfail_op); zstencil->cc0.stencil_pass_depth_pass_op = translate_stencil_op(templ->stencil[0].zpass_op); zstencil->cc1.stencil_write_mask = templ->stencil[0].writemask; zstencil->cc1.stencil_test_mask = templ->stencil[0].valuemask; if (templ->stencil[1].enabled) { zstencil->cc0.bf_stencil_enable = 1; zstencil->cc0.bf_stencil_func = brw_translate_compare_func(templ->stencil[1].func); zstencil->cc0.bf_stencil_fail_op = translate_stencil_op(templ->stencil[1].fail_op); zstencil->cc0.bf_stencil_pass_depth_fail_op = translate_stencil_op(templ->stencil[1].zfail_op); zstencil->cc0.bf_stencil_pass_depth_pass_op = translate_stencil_op(templ->stencil[1].zpass_op); zstencil->cc2.bf_stencil_write_mask = templ->stencil[1].writemask; zstencil->cc2.bf_stencil_test_mask = templ->stencil[1].valuemask; } zstencil->cc0.stencil_write_enable = (zstencil->cc1.stencil_write_mask || zstencil->cc2.bf_stencil_write_mask); } if (templ->alpha.enabled) { zstencil->cc3.alpha_test = 1; zstencil->cc3.alpha_test_func = brw_translate_compare_func(templ->alpha.func); zstencil->cc3.alpha_test_format = BRW_ALPHATEST_FORMAT_UNORM8; zstencil->cc7.alpha_ref.ub[0] = float_to_ubyte(templ->alpha.ref_value); } if (templ->depth.enabled) { zstencil->cc2.depth_test = 1; zstencil->cc2.depth_test_function = brw_translate_compare_func(templ->depth.func); zstencil->cc2.depth_write_enable = templ->depth.writemask; } }
/** * When a whole surface is being cleared to a value we can avoid * fetching tiles above. * Save the color and set a 'clearflag' for each tile of the screen. */ void lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba, uint clearValue) { struct pipe_transfer *pt = tc->transfer; const unsigned w = pt->width; const unsigned h = pt->height; unsigned x, y, chan; for(chan = 0; chan < 4; ++chan) tc->clear_color[chan] = float_to_ubyte(rgba[chan]); tc->clear_val = clearValue; /* push the tile to all positions marked as clear */ for (y = 0; y < h; y += TILE_SIZE) { for (x = 0; x < w; x += TILE_SIZE) { struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE]; tile->status = LP_TILE_STATUS_CLEAR; } } }
void util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src, unsigned src_stride, unsigned width, unsigned height) { unsigned x, y, i, j, k; for(y = 0; y < height; y += 4) { uint8_t *dst = dst_row; for(x = 0; x < width; x += 4) { uint8_t tmp[4][4][4]; for(j = 0; j < 4; ++j) { for(i = 0; i < 4; ++i) { for(k = 0; k < 4; ++k) { tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]); } } } util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0); dst += 16; } dst_row += 4*dst_stride/sizeof(*dst_row); } }
void fd2_emit_state(struct fd_context *ctx, const enum fd_dirty_3d_state dirty) { struct fd2_blend_stateobj *blend = fd2_blend_stateobj(ctx->blend); struct fd2_zsa_stateobj *zsa = fd2_zsa_stateobj(ctx->zsa); struct fd_ringbuffer *ring = ctx->batch->draw; /* NOTE: we probably want to eventually refactor this so each state * object handles emitting it's own state.. although the mapping of * state to registers is not always orthogonal, sometimes a single * register contains bitfields coming from multiple state objects, * so not sure the best way to deal with that yet. */ if (dirty & FD_DIRTY_SAMPLE_MASK) { OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_AA_MASK)); OUT_RING(ring, ctx->sample_mask); } if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_STENCIL_REF)) { struct pipe_stencil_ref *sr = &ctx->stencil_ref; OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_DEPTHCONTROL)); OUT_RING(ring, zsa->rb_depthcontrol); OUT_PKT3(ring, CP_SET_CONSTANT, 4); OUT_RING(ring, CP_REG(REG_A2XX_RB_STENCILREFMASK_BF)); OUT_RING(ring, zsa->rb_stencilrefmask_bf | A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[1])); OUT_RING(ring, zsa->rb_stencilrefmask | A2XX_RB_STENCILREFMASK_STENCILREF(sr->ref_value[0])); OUT_RING(ring, zsa->rb_alpha_ref); } if (ctx->rasterizer && dirty & FD_DIRTY_RASTERIZER) { struct fd2_rasterizer_stateobj *rasterizer = fd2_rasterizer_stateobj(ctx->rasterizer); OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_CLIP_CNTL)); OUT_RING(ring, rasterizer->pa_cl_clip_cntl); OUT_RING(ring, rasterizer->pa_su_sc_mode_cntl | A2XX_PA_SU_SC_MODE_CNTL_VTX_WINDOW_OFFSET_ENABLE); OUT_PKT3(ring, CP_SET_CONSTANT, 5); OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_POINT_SIZE)); OUT_RING(ring, rasterizer->pa_su_point_size); OUT_RING(ring, rasterizer->pa_su_point_minmax); OUT_RING(ring, rasterizer->pa_su_line_cntl); OUT_RING(ring, rasterizer->pa_sc_line_stipple); OUT_PKT3(ring, CP_SET_CONSTANT, 6); OUT_RING(ring, CP_REG(REG_A2XX_PA_SU_VTX_CNTL)); OUT_RING(ring, rasterizer->pa_su_vtx_cntl); OUT_RING(ring, fui(1.0)); /* PA_CL_GB_VERT_CLIP_ADJ */ OUT_RING(ring, fui(1.0)); /* PA_CL_GB_VERT_DISC_ADJ */ OUT_RING(ring, fui(1.0)); /* PA_CL_GB_HORZ_CLIP_ADJ */ OUT_RING(ring, fui(1.0)); /* PA_CL_GB_HORZ_DISC_ADJ */ } /* NOTE: scissor enabled bit is part of rasterizer state: */ if (dirty & (FD_DIRTY_SCISSOR | FD_DIRTY_RASTERIZER)) { struct pipe_scissor_state *scissor = fd_context_get_scissor(ctx); OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_SCISSOR_TL)); OUT_RING(ring, xy2d(scissor->minx, /* PA_SC_WINDOW_SCISSOR_TL */ scissor->miny)); OUT_RING(ring, xy2d(scissor->maxx, /* PA_SC_WINDOW_SCISSOR_BR */ scissor->maxy)); ctx->batch->max_scissor.minx = MIN2(ctx->batch->max_scissor.minx, scissor->minx); ctx->batch->max_scissor.miny = MIN2(ctx->batch->max_scissor.miny, scissor->miny); ctx->batch->max_scissor.maxx = MAX2(ctx->batch->max_scissor.maxx, scissor->maxx); ctx->batch->max_scissor.maxy = MAX2(ctx->batch->max_scissor.maxy, scissor->maxy); } if (dirty & FD_DIRTY_VIEWPORT) { OUT_PKT3(ring, CP_SET_CONSTANT, 7); OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VPORT_XSCALE)); OUT_RING(ring, fui(ctx->viewport.scale[0])); /* PA_CL_VPORT_XSCALE */ OUT_RING(ring, fui(ctx->viewport.translate[0])); /* PA_CL_VPORT_XOFFSET */ OUT_RING(ring, fui(ctx->viewport.scale[1])); /* PA_CL_VPORT_YSCALE */ OUT_RING(ring, fui(ctx->viewport.translate[1])); /* PA_CL_VPORT_YOFFSET */ OUT_RING(ring, fui(ctx->viewport.scale[2])); /* PA_CL_VPORT_ZSCALE */ OUT_RING(ring, fui(ctx->viewport.translate[2])); /* PA_CL_VPORT_ZOFFSET */ OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_PA_CL_VTE_CNTL)); OUT_RING(ring, A2XX_PA_CL_VTE_CNTL_VTX_W0_FMT | A2XX_PA_CL_VTE_CNTL_VPORT_X_SCALE_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_X_OFFSET_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Y_SCALE_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Y_OFFSET_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Z_SCALE_ENA | A2XX_PA_CL_VTE_CNTL_VPORT_Z_OFFSET_ENA); } if (dirty & (FD_DIRTY_PROG | FD_DIRTY_VTXSTATE | FD_DIRTY_TEXSTATE)) { fd2_program_validate(ctx); fd2_program_emit(ring, &ctx->prog); } if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONST)) { emit_constants(ring, VS_CONST_BASE * 4, &ctx->constbuf[PIPE_SHADER_VERTEX], (dirty & FD_DIRTY_PROG) ? ctx->prog.vp : NULL); emit_constants(ring, PS_CONST_BASE * 4, &ctx->constbuf[PIPE_SHADER_FRAGMENT], (dirty & FD_DIRTY_PROG) ? ctx->prog.fp : NULL); } if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_ZSA)) { OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_COLORCONTROL)); OUT_RING(ring, blend ? zsa->rb_colorcontrol | blend->rb_colorcontrol : 0); } if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_FRAMEBUFFER)) { enum pipe_format format = pipe_surface_format(ctx->batch->framebuffer.cbufs[0]); bool has_alpha = util_format_has_alpha(format); OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_CONTROL)); OUT_RING(ring, blend ? blend->rb_blendcontrol_alpha | COND(has_alpha, blend->rb_blendcontrol_rgb) | COND(!has_alpha, blend->rb_blendcontrol_no_alpha_rgb) : 0); OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_COLOR_MASK)); OUT_RING(ring, blend ? blend->rb_colormask : 0xf); } if (dirty & FD_DIRTY_BLEND_COLOR) { OUT_PKT3(ring, CP_SET_CONSTANT, 5); OUT_RING(ring, CP_REG(REG_A2XX_RB_BLEND_RED)); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[0])); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[1])); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[2])); OUT_RING(ring, float_to_ubyte(ctx->blend_color.color[3])); } if (dirty & (FD_DIRTY_TEX | FD_DIRTY_PROG)) emit_textures(ring, ctx); }
/** * Called by vbuf code when we're about to draw something. * * This function stores all dirty state in the current scene's display list * memory, via lp_scene_alloc(). We can not pass pointers of mutable state to * the JIT functions, as the JIT functions will be called later on, most likely * on a different thread. * * When processing dirty state it is imperative that we don't refer to any * pointers previously allocated with lp_scene_alloc() in this function (or any * function) as they may belong to a scene freed since then. */ static boolean try_update_scene_state( struct lp_setup_context *setup ) { static const float fake_const_buf[4]; boolean new_scene = (setup->fs.stored == NULL); struct lp_scene *scene = setup->scene; unsigned i; assert(scene); if (setup->dirty & LP_SETUP_NEW_VIEWPORTS) { /* * Record new depth range state for changes due to viewport updates. * * TODO: Collapse the existing viewport and depth range information * into one structure, for access by JIT. */ struct lp_jit_viewport *stored; stored = (struct lp_jit_viewport *) lp_scene_alloc(scene, sizeof setup->viewports); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, setup->viewports, sizeof setup->viewports); setup->fs.current.jit_context.viewports = stored; setup->dirty |= LP_SETUP_NEW_FS; } if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { uint8_t *stored; float* fstored; unsigned i, j; unsigned size; /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */ size = 4 * 16 * sizeof(uint8_t); size += (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float); stored = lp_scene_alloc_aligned(scene, size, LP_MIN_VECTOR_ALIGN); if (!stored) { assert(!new_scene); return FALSE; } /* Store floating point colour */ fstored = (float*)(stored + 4*16); for (i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) { fstored[i] = setup->blend_color.current.color[i % 4]; } /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); for (j = 0; j < 16; ++j) stored[i*16 + j] = c; } setup->blend_color.stored = stored; setup->fs.current.jit_context.u8_blend_color = stored; setup->fs.current.jit_context.f_blend_color = fstored; setup->dirty |= LP_SETUP_NEW_FS; } if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { for (i = 0; i < ARRAY_SIZE(setup->constants); ++i) { struct pipe_resource *buffer = setup->constants[i].current.buffer; const unsigned current_size = MIN2(setup->constants[i].current.buffer_size, LP_MAX_TGSI_CONST_BUFFER_SIZE); const ubyte *current_data = NULL; int num_constants; STATIC_ASSERT(DATA_BLOCK_SIZE >= LP_MAX_TGSI_CONST_BUFFER_SIZE); if (buffer) { /* resource buffer */ current_data = (ubyte *) llvmpipe_resource_data(buffer); } else if (setup->constants[i].current.user_buffer) { /* user-space buffer */ current_data = (ubyte *) setup->constants[i].current.user_buffer; } if (current_data) { current_data += setup->constants[i].current.buffer_offset; /* TODO: copy only the actually used constants? */ if (setup->constants[i].stored_size != current_size || !setup->constants[i].stored_data || memcmp(setup->constants[i].stored_data, current_data, current_size) != 0) { void *stored; stored = lp_scene_alloc(scene, current_size); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, current_data, current_size); setup->constants[i].stored_size = current_size; setup->constants[i].stored_data = stored; } setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data; } else { setup->constants[i].stored_size = 0; setup->constants[i].stored_data = NULL; setup->fs.current.jit_context.constants[i] = fake_const_buf; } num_constants = setup->constants[i].stored_size / (sizeof(float) * 4); setup->fs.current.jit_context.num_constants[i] = num_constants; setup->dirty |= LP_SETUP_NEW_FS; } } if (setup->dirty & LP_SETUP_NEW_FS) { if (!setup->fs.stored || memcmp(setup->fs.stored, &setup->fs.current, sizeof setup->fs.current) != 0) { struct lp_rast_state *stored; /* The fs state that's been stored in the scene is different from * the new, current state. So allocate a new lp_rast_state object * and append it to the bin's setup data buffer. */ stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, &setup->fs.current, sizeof setup->fs.current); setup->fs.stored = stored; /* The scene now references the textures in the rasterization * state record. Note that now. */ for (i = 0; i < ARRAY_SIZE(setup->fs.current_tex); i++) { if (setup->fs.current_tex[i]) { if (!lp_scene_add_resource_reference(scene, setup->fs.current_tex[i], new_scene)) { assert(!new_scene); return FALSE; } } } } } if (setup->dirty & LP_SETUP_NEW_SCISSOR) { unsigned i; for (i = 0; i < PIPE_MAX_VIEWPORTS; ++i) { setup->draw_regions[i] = setup->framebuffer; if (setup->scissor_test) { u_rect_possible_intersection(&setup->scissors[i], &setup->draw_regions[i]); } } } setup->dirty = 0; assert(setup->fs.stored); return TRUE; }
/** * Called by vbuf code when we're about to draw something. */ static boolean try_update_scene_state( struct lp_setup_context *setup ) { boolean new_scene = (setup->fs.stored == NULL); struct lp_scene *scene = setup->scene; unsigned i; assert(scene); if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { uint8_t *stored; float* fstored; unsigned i, j; unsigned size; /* Alloc u8_blend_color (16 x i8) and f_blend_color (4 or 8 x f32) */ size = 4 * 16 * sizeof(uint8_t); size += (LP_MAX_VECTOR_LENGTH / 4) * sizeof(float); stored = lp_scene_alloc_aligned(scene, size, LP_MAX_VECTOR_LENGTH); if (!stored) { assert(!new_scene); return FALSE; } /* Store floating point colour */ fstored = (float*)(stored + 4*16); for (i = 0; i < (LP_MAX_VECTOR_LENGTH / 4); ++i) { fstored[i] = setup->blend_color.current.color[i % 4]; } /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); for (j = 0; j < 16; ++j) stored[i*16 + j] = c; } setup->blend_color.stored = stored; setup->fs.current.jit_context.u8_blend_color = stored; setup->fs.current.jit_context.f_blend_color = fstored; setup->dirty |= LP_SETUP_NEW_FS; } if (setup->dirty & LP_SETUP_NEW_CONSTANTS) { for (i = 0; i < Elements(setup->constants); ++i) { struct pipe_resource *buffer = setup->constants[i].current.buffer; const unsigned current_size = setup->constants[i].current.buffer_size; const ubyte *current_data = NULL; if (buffer) { /* resource buffer */ current_data = (ubyte *) llvmpipe_resource_data(buffer); } else if (setup->constants[i].current.user_buffer) { /* user-space buffer */ current_data = (ubyte *) setup->constants[i].current.user_buffer; } if (current_data) { current_data += setup->constants[i].current.buffer_offset; /* TODO: copy only the actually used constants? */ if (setup->constants[i].stored_size != current_size || !setup->constants[i].stored_data || memcmp(setup->constants[i].stored_data, current_data, current_size) != 0) { void *stored; stored = lp_scene_alloc(scene, current_size); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, current_data, current_size); setup->constants[i].stored_size = current_size; setup->constants[i].stored_data = stored; } } else { setup->constants[i].stored_size = 0; setup->constants[i].stored_data = NULL; } setup->fs.current.jit_context.constants[i] = setup->constants[i].stored_data; setup->dirty |= LP_SETUP_NEW_FS; } } if (setup->dirty & LP_SETUP_NEW_FS) { if (!setup->fs.stored || memcmp(setup->fs.stored, &setup->fs.current, sizeof setup->fs.current) != 0) { struct lp_rast_state *stored; /* The fs state that's been stored in the scene is different from * the new, current state. So allocate a new lp_rast_state object * and append it to the bin's setup data buffer. */ stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, &setup->fs.current, sizeof setup->fs.current); setup->fs.stored = stored; /* The scene now references the textures in the rasterization * state record. Note that now. */ for (i = 0; i < Elements(setup->fs.current_tex); i++) { if (setup->fs.current_tex[i]) { if (!lp_scene_add_resource_reference(scene, setup->fs.current_tex[i], new_scene)) { assert(!new_scene); return FALSE; } } } } } if (setup->dirty & LP_SETUP_NEW_SCISSOR) { setup->draw_region = setup->framebuffer; if (setup->scissor_test) { u_rect_possible_intersection(&setup->scissor, &setup->draw_region); } } setup->dirty = 0; assert(setup->fs.stored); return TRUE; }
/** * Called by vbuf code when we're about to draw something. */ static boolean try_update_scene_state( struct lp_setup_context *setup ) { boolean new_scene = (setup->fs.stored == NULL); struct lp_scene *scene = setup->scene; assert(scene); if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { uint8_t *stored; unsigned i, j; stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); if (!stored) { assert(!new_scene); return FALSE; } /* smear each blend color component across 16 ubyte elements */ for (i = 0; i < 4; ++i) { uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); for (j = 0; j < 16; ++j) stored[i*16 + j] = c; } setup->blend_color.stored = stored; setup->fs.current.jit_context.blend_color = setup->blend_color.stored; setup->dirty |= LP_SETUP_NEW_FS; } if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { struct pipe_resource *buffer = setup->constants.current; if(buffer) { unsigned current_size = buffer->width0; const void *current_data = llvmpipe_resource_data(buffer); /* TODO: copy only the actually used constants? */ if(setup->constants.stored_size != current_size || !setup->constants.stored_data || memcmp(setup->constants.stored_data, current_data, current_size) != 0) { void *stored; stored = lp_scene_alloc(scene, current_size); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, current_data, current_size); setup->constants.stored_size = current_size; setup->constants.stored_data = stored; } } else { setup->constants.stored_size = 0; setup->constants.stored_data = NULL; } setup->fs.current.jit_context.constants = setup->constants.stored_data; setup->dirty |= LP_SETUP_NEW_FS; } if (setup->dirty & LP_SETUP_NEW_FS) { if (!setup->fs.stored || memcmp(setup->fs.stored, &setup->fs.current, sizeof setup->fs.current) != 0) { struct lp_rast_state *stored; uint i; /* The fs state that's been stored in the scene is different from * the new, current state. So allocate a new lp_rast_state object * and append it to the bin's setup data buffer. */ stored = (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); if (!stored) { assert(!new_scene); return FALSE; } memcpy(stored, &setup->fs.current, sizeof setup->fs.current); setup->fs.stored = stored; /* The scene now references the textures in the rasterization * state record. Note that now. */ for (i = 0; i < Elements(setup->fs.current_tex); i++) { if (setup->fs.current_tex[i]) { if (!lp_scene_add_resource_reference(scene, setup->fs.current_tex[i], new_scene)) { assert(!new_scene); return FALSE; } } } } } if (setup->dirty & LP_SETUP_NEW_SCISSOR) { setup->draw_region = setup->framebuffer; if (setup->scissor_test) { u_rect_possible_intersection(&setup->scissor, &setup->draw_region); } } setup->dirty = 0; assert(setup->fs.stored); return TRUE; }
static boolean lp_setup_try_clear( struct lp_setup_context *setup, const float *color, double depth, unsigned stencil, unsigned flags ) { uint32_t zsmask = 0; uint32_t zsvalue = 0; union lp_rast_cmd_arg color_arg; unsigned i; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); if (flags & PIPE_CLEAR_COLOR) { for (i = 0; i < 4; i++) color_arg.clear_color[i] = float_to_ubyte(color[i]); } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { unsigned zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; unsigned smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; zsvalue = util_pack_z_stencil(setup->fb.zsbuf->format, depth, stencil); zsmask = util_pack_uint_z_stencil(setup->fb.zsbuf->format, zmask, smask); } if (setup->state == SETUP_ACTIVE) { struct lp_scene *scene = setup->scene; /* Add the clear to existing scene. In the unusual case where * both color and depth-stencil are being cleared when there's * already been some rendering, we could discard the currently * binned scene and start again, but I don't see that as being * a common usage. */ if (flags & PIPE_CLEAR_COLOR) { if (!lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_COLOR, color_arg )) return FALSE; } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { if (!lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs(zsvalue, zsmask) )) return FALSE; } } else { /* Put ourselves into the 'pre-clear' state, specifically to try * and accumulate multiple clears to color and depth_stencil * buffers which the app or state-tracker might issue * separately. */ set_scene_state( setup, SETUP_CLEARED, __FUNCTION__ ); setup->clear.flags |= flags; if (flags & PIPE_CLEAR_DEPTHSTENCIL) { setup->clear.zsmask |= zsmask; setup->clear.zsvalue = (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); } if (flags & PIPE_CLEAR_COLOR) { memcpy(setup->clear.color.clear_color, &color_arg, sizeof color_arg); } } return TRUE; }
static void write_texture_border_color(struct vc5_job *job, struct vc5_cl_out **uniforms, struct vc5_texture_stateobj *texstate, uint32_t unit) { struct pipe_sampler_state *sampler = texstate->samplers[unit]; struct pipe_sampler_view *texture = texstate->textures[unit]; struct vc5_resource *rsc = vc5_resource(texture->texture); union util_color uc; const struct util_format_description *tex_format_desc = util_format_description(texture->format); float border_color[4]; for (int i = 0; i < 4; i++) border_color[i] = sampler->border_color.f[i]; if (util_format_is_srgb(texture->format)) { for (int i = 0; i < 3; i++) border_color[i] = util_format_linear_to_srgb_float(border_color[i]); } /* Turn the border color into the layout of channels that it would * have when stored as texture contents. */ float storage_color[4]; util_format_unswizzle_4f(storage_color, border_color, tex_format_desc->swizzle); /* Now, pack so that when the vc5_format-sampled texture contents are * replaced with our border color, the vc5_get_format_swizzle() * swizzling will get the right channels. */ if (util_format_is_depth_or_stencil(texture->format)) { uc.ui[0] = util_pack_z(PIPE_FORMAT_Z24X8_UNORM, sampler->border_color.f[0]) << 8; } else { switch (rsc->vc5_format) { default: case VC5_TEXTURE_TYPE_RGBA8888: util_pack_color(storage_color, PIPE_FORMAT_R8G8B8A8_UNORM, &uc); break; case VC5_TEXTURE_TYPE_RGBA4444: util_pack_color(storage_color, PIPE_FORMAT_A8B8G8R8_UNORM, &uc); break; case VC5_TEXTURE_TYPE_RGB565: util_pack_color(storage_color, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); break; case VC5_TEXTURE_TYPE_ALPHA: uc.ui[0] = float_to_ubyte(storage_color[0]) << 24; break; case VC5_TEXTURE_TYPE_LUMALPHA: uc.ui[0] = ((float_to_ubyte(storage_color[1]) << 24) | (float_to_ubyte(storage_color[0]) << 0)); break; } } cl_aligned_u32(uniforms, uc.ui[0]); }
/* Compare old and new render states and emit differences between them * to hardware. Simplest implementation would be to emit the whole of * the "to" state. */ static enum pipe_error emit_rss(struct svga_context *svga, unsigned dirty) { struct svga_screen *screen = svga_screen(svga->pipe.screen); struct rs_queue queue; float point_size_min; queue.rs_count = 0; if (dirty & SVGA_NEW_BLEND) { const struct svga_blend_state *curr = svga->curr.blend; EMIT_RS( svga, curr->rt[0].writemask, COLORWRITEENABLE, fail ); EMIT_RS( svga, curr->rt[0].blend_enable, BLENDENABLE, fail ); if (curr->rt[0].blend_enable) { EMIT_RS( svga, curr->rt[0].srcblend, SRCBLEND, fail ); EMIT_RS( svga, curr->rt[0].dstblend, DSTBLEND, fail ); EMIT_RS( svga, curr->rt[0].blendeq, BLENDEQUATION, fail ); EMIT_RS( svga, curr->rt[0].separate_alpha_blend_enable, SEPARATEALPHABLENDENABLE, fail ); if (curr->rt[0].separate_alpha_blend_enable) { EMIT_RS( svga, curr->rt[0].srcblend_alpha, SRCBLENDALPHA, fail ); EMIT_RS( svga, curr->rt[0].dstblend_alpha, DSTBLENDALPHA, fail ); EMIT_RS( svga, curr->rt[0].blendeq_alpha, BLENDEQUATIONALPHA, fail ); } } } if (dirty & SVGA_NEW_BLEND_COLOR) { uint32 color; uint32 r = float_to_ubyte(svga->curr.blend_color.color[0]); uint32 g = float_to_ubyte(svga->curr.blend_color.color[1]); uint32 b = float_to_ubyte(svga->curr.blend_color.color[2]); uint32 a = float_to_ubyte(svga->curr.blend_color.color[3]); color = (a << 24) | (r << 16) | (g << 8) | b; EMIT_RS( svga, color, BLENDCOLOR, fail ); } if (dirty & (SVGA_NEW_DEPTH_STENCIL | SVGA_NEW_RAST)) { const struct svga_depth_stencil_state *curr = svga->curr.depth; const struct svga_rasterizer_state *rast = svga->curr.rast; if (!curr->stencil[0].enabled) { /* Stencil disabled */ EMIT_RS( svga, FALSE, STENCILENABLE, fail ); EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail ); } else if (curr->stencil[0].enabled && !curr->stencil[1].enabled) { /* Regular stencil */ EMIT_RS( svga, TRUE, STENCILENABLE, fail ); EMIT_RS( svga, FALSE, STENCILENABLE2SIDED, fail ); EMIT_RS( svga, curr->stencil[0].func, STENCILFUNC, fail ); EMIT_RS( svga, curr->stencil[0].fail, STENCILFAIL, fail ); EMIT_RS( svga, curr->stencil[0].zfail, STENCILZFAIL, fail ); EMIT_RS( svga, curr->stencil[0].pass, STENCILPASS, fail ); EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail ); EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail ); } else { int cw, ccw; /* Hardware frontwinding is always CW, so if ours is also CW, * then our definition of front face agrees with hardware. * Otherwise need to flip. */ if (rast->templ.front_ccw) { ccw = 0; cw = 1; } else { ccw = 1; cw = 0; } /* Twoside stencil */ EMIT_RS( svga, TRUE, STENCILENABLE, fail ); EMIT_RS( svga, TRUE, STENCILENABLE2SIDED, fail ); EMIT_RS( svga, curr->stencil[cw].func, STENCILFUNC, fail ); EMIT_RS( svga, curr->stencil[cw].fail, STENCILFAIL, fail ); EMIT_RS( svga, curr->stencil[cw].zfail, STENCILZFAIL, fail ); EMIT_RS( svga, curr->stencil[cw].pass, STENCILPASS, fail ); EMIT_RS( svga, curr->stencil[ccw].func, CCWSTENCILFUNC, fail ); EMIT_RS( svga, curr->stencil[ccw].fail, CCWSTENCILFAIL, fail ); EMIT_RS( svga, curr->stencil[ccw].zfail, CCWSTENCILZFAIL, fail ); EMIT_RS( svga, curr->stencil[ccw].pass, CCWSTENCILPASS, fail ); EMIT_RS( svga, curr->stencil_mask, STENCILMASK, fail ); EMIT_RS( svga, curr->stencil_writemask, STENCILWRITEMASK, fail ); } EMIT_RS( svga, curr->zenable, ZENABLE, fail ); if (curr->zenable) { EMIT_RS( svga, curr->zfunc, ZFUNC, fail ); EMIT_RS( svga, curr->zwriteenable, ZWRITEENABLE, fail ); } EMIT_RS( svga, curr->alphatestenable, ALPHATESTENABLE, fail ); if (curr->alphatestenable) { EMIT_RS( svga, curr->alphafunc, ALPHAFUNC, fail ); EMIT_RS_FLOAT( svga, curr->alpharef, ALPHAREF, fail ); } } if (dirty & SVGA_NEW_STENCIL_REF) { EMIT_RS( svga, svga->curr.stencil_ref.ref_value[0], STENCILREF, fail ); } if (dirty & (SVGA_NEW_RAST | SVGA_NEW_NEED_PIPELINE)) { const struct svga_rasterizer_state *curr = svga->curr.rast; unsigned cullmode = curr->cullmode; /* Shademode: still need to rearrange index list to move * flat-shading PV first vertex. */ EMIT_RS( svga, curr->shademode, SHADEMODE, fail ); /* Don't do culling while the software pipeline is active. It * does it for us, and additionally introduces potentially * back-facing triangles. */ if (svga->state.sw.need_pipeline) cullmode = SVGA3D_FACE_NONE; point_size_min = util_get_min_point_size(&curr->templ); EMIT_RS( svga, cullmode, CULLMODE, fail ); EMIT_RS( svga, curr->scissortestenable, SCISSORTESTENABLE, fail ); EMIT_RS( svga, curr->multisampleantialias, MULTISAMPLEANTIALIAS, fail ); EMIT_RS( svga, curr->lastpixel, LASTPIXEL, fail ); EMIT_RS( svga, curr->linepattern, LINEPATTERN, fail ); EMIT_RS_FLOAT( svga, curr->pointsize, POINTSIZE, fail ); EMIT_RS_FLOAT( svga, point_size_min, POINTSIZEMIN, fail ); EMIT_RS_FLOAT( svga, screen->maxPointSize, POINTSIZEMAX, fail ); EMIT_RS( svga, curr->pointsprite, POINTSPRITEENABLE, fail); } if (dirty & (SVGA_NEW_RAST | SVGA_NEW_FRAME_BUFFER | SVGA_NEW_NEED_PIPELINE)) { const struct svga_rasterizer_state *curr = svga->curr.rast; float slope = 0.0; float bias = 0.0; /* Need to modify depth bias according to bound depthbuffer * format. Don't do hardware depthbias while the software * pipeline is active. */ if (!svga->state.sw.need_pipeline && svga->curr.framebuffer.zsbuf) { slope = curr->slopescaledepthbias; bias = svga->curr.depthscale * curr->depthbias; } EMIT_RS_FLOAT( svga, slope, SLOPESCALEDEPTHBIAS, fail ); EMIT_RS_FLOAT( svga, bias, DEPTHBIAS, fail ); } if (dirty & SVGA_NEW_FRAME_BUFFER) { /* XXX: we only look at the first color buffer's sRGB state */ float gamma = 1.0f; if (svga->curr.framebuffer.cbufs[0] && util_format_is_srgb(svga->curr.framebuffer.cbufs[0]->format)) { gamma = 2.2f; } EMIT_RS_FLOAT(svga, gamma, OUTPUTGAMMA, fail); } if (dirty & SVGA_NEW_RAST) { /* bitmask of the enabled clip planes */ unsigned enabled = svga->curr.rast->templ.clip_plane_enable; EMIT_RS( svga, enabled, CLIPPLANEENABLE, fail ); } if (queue.rs_count) { SVGA3dRenderState *rs; if (SVGA3D_BeginSetRenderState( svga->swc, &rs, queue.rs_count ) != PIPE_OK) goto fail; memcpy( rs, queue.rs, queue.rs_count * sizeof queue.rs[0]); SVGA_FIFOCommitAll( svga->swc ); } return PIPE_OK; fail: /* XXX: need to poison cached hardware state on failure to ensure * dirty state gets re-emitted. Fix this by re-instating partial * FIFOCommit command and only updating cached hw state once the * initial allocation has succeeded. */ memset(svga->state.hw_draw.rs, 0xcd, sizeof(svga->state.hw_draw.rs)); return PIPE_ERROR_OUT_OF_MEMORY; }
static void * i915_create_sampler_state(struct pipe_context *pipe, const struct pipe_sampler_state *sampler) { struct i915_sampler_state *cso = CALLOC_STRUCT( i915_sampler_state ); const unsigned ws = sampler->wrap_s; const unsigned wt = sampler->wrap_t; const unsigned wr = sampler->wrap_r; unsigned minFilt, magFilt; unsigned mipFilt; cso->templ = *sampler; mipFilt = translate_mip_filter(sampler->min_mip_filter); minFilt = translate_img_filter( sampler->min_img_filter ); magFilt = translate_img_filter( sampler->mag_img_filter ); if (sampler->max_anisotropy > 1) minFilt = magFilt = FILTER_ANISOTROPIC; if (sampler->max_anisotropy > 2) { cso->state[0] |= SS2_MAX_ANISO_4; } { int b = (int) (sampler->lod_bias * 16.0); b = CLAMP(b, -256, 255); cso->state[0] |= ((b << SS2_LOD_BIAS_SHIFT) & SS2_LOD_BIAS_MASK); } /* Shadow: */ if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { cso->state[0] |= (SS2_SHADOW_ENABLE | i915_translate_shadow_compare_func(sampler->compare_func)); minFilt = FILTER_4X4_FLAT; magFilt = FILTER_4X4_FLAT; } cso->state[0] |= ((minFilt << SS2_MIN_FILTER_SHIFT) | (mipFilt << SS2_MIP_FILTER_SHIFT) | (magFilt << SS2_MAG_FILTER_SHIFT)); cso->state[1] |= ((translate_wrap_mode(ws) << SS3_TCX_ADDR_MODE_SHIFT) | (translate_wrap_mode(wt) << SS3_TCY_ADDR_MODE_SHIFT) | (translate_wrap_mode(wr) << SS3_TCZ_ADDR_MODE_SHIFT)); if (sampler->normalized_coords) cso->state[1] |= SS3_NORMALIZED_COORDS; { int minlod = (int) (16.0 * sampler->min_lod); int maxlod = (int) (16.0 * sampler->max_lod); minlod = CLAMP(minlod, 0, 16 * 11); maxlod = CLAMP(maxlod, 0, 16 * 11); if (minlod > maxlod) maxlod = minlod; cso->minlod = minlod; cso->maxlod = maxlod; } { ubyte r = float_to_ubyte(sampler->border_color.f[0]); ubyte g = float_to_ubyte(sampler->border_color.f[1]); ubyte b = float_to_ubyte(sampler->border_color.f[2]); ubyte a = float_to_ubyte(sampler->border_color.f[3]); cso->state[2] = I915PACKCOLOR8888(r, g, b, a); } return cso; }
static void * i915_create_depth_stencil_state(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *depth_stencil) { struct i915_depth_stencil_state *cso = CALLOC_STRUCT( i915_depth_stencil_state ); { int testmask = depth_stencil->stencil[0].valuemask & 0xff; int writemask = depth_stencil->stencil[0].writemask & 0xff; cso->stencil_modes4 |= (_3DSTATE_MODES_4_CMD | ENABLE_STENCIL_TEST_MASK | STENCIL_TEST_MASK(testmask) | ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(writemask)); } if (depth_stencil->stencil[0].enabled) { int test = i915_translate_compare_func(depth_stencil->stencil[0].func); int fop = i915_translate_stencil_op(depth_stencil->stencil[0].fail_op); int dfop = i915_translate_stencil_op(depth_stencil->stencil[0].zfail_op); int dpop = i915_translate_stencil_op(depth_stencil->stencil[0].zpass_op); cso->stencil_LIS5 |= (S5_STENCIL_TEST_ENABLE | S5_STENCIL_WRITE_ENABLE | (test << S5_STENCIL_TEST_FUNC_SHIFT) | (fop << S5_STENCIL_FAIL_SHIFT) | (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) | (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT)); } if (depth_stencil->stencil[1].enabled) { int test = i915_translate_compare_func(depth_stencil->stencil[1].func); int fop = i915_translate_stencil_op(depth_stencil->stencil[1].fail_op); int dfop = i915_translate_stencil_op(depth_stencil->stencil[1].zfail_op); int dpop = i915_translate_stencil_op(depth_stencil->stencil[1].zpass_op); int tmask = depth_stencil->stencil[1].valuemask & 0xff; int wmask = depth_stencil->stencil[1].writemask & 0xff; cso->bfo[0] = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_FUNCS | BFO_ENABLE_STENCIL_TWO_SIDE | BFO_ENABLE_STENCIL_REF | BFO_STENCIL_TWO_SIDE | (test << BFO_STENCIL_TEST_SHIFT) | (fop << BFO_STENCIL_FAIL_SHIFT) | (dfop << BFO_STENCIL_PASS_Z_FAIL_SHIFT) | (dpop << BFO_STENCIL_PASS_Z_PASS_SHIFT)); cso->bfo[1] = (_3DSTATE_BACKFACE_STENCIL_MASKS | BFM_ENABLE_STENCIL_TEST_MASK | BFM_ENABLE_STENCIL_WRITE_MASK | (tmask << BFM_STENCIL_TEST_MASK_SHIFT) | (wmask << BFM_STENCIL_WRITE_MASK_SHIFT)); } else { /* This actually disables two-side stencil: The bit set is a * modify-enable bit to indicate we are changing the two-side * setting. Then there is a symbolic zero to show that we are * setting the flag to zero/off. */ cso->bfo[0] = (_3DSTATE_BACKFACE_STENCIL_OPS | BFO_ENABLE_STENCIL_TWO_SIDE | 0); cso->bfo[1] = 0; } if (depth_stencil->depth.enabled) { int func = i915_translate_compare_func(depth_stencil->depth.func); cso->depth_LIS6 |= (S6_DEPTH_TEST_ENABLE | (func << S6_DEPTH_TEST_FUNC_SHIFT)); if (depth_stencil->depth.writemask) cso->depth_LIS6 |= S6_DEPTH_WRITE_ENABLE; } if (depth_stencil->alpha.enabled) { int test = i915_translate_compare_func(depth_stencil->alpha.func); ubyte refByte = float_to_ubyte(depth_stencil->alpha.ref_value); cso->depth_LIS6 |= (S6_ALPHA_TEST_ENABLE | (test << S6_ALPHA_TEST_FUNC_SHIFT) | (((unsigned) refByte) << S6_ALPHA_REF_SHIFT)); } return cso; }
static void * nv30_zsa_state_create(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *cso) { struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d; struct nv30_zsa_stateobj *so; so = CALLOC_STRUCT(nv30_zsa_stateobj); if (!so) return NULL; so->pipe = *cso; SB_MTHD30(so, DEPTH_FUNC, 3); SB_DATA (so, nvgl_comparison_op(cso->depth.func)); SB_DATA (so, cso->depth.writemask); SB_DATA (so, cso->depth.enabled); if (eng3d->oclass == NV35_3D_CLASS || eng3d->oclass >= NV40_3D_CLASS) { SB_MTHD35(so, DEPTH_BOUNDS_TEST_ENABLE, 3); SB_DATA (so, cso->depth.bounds_test); SB_DATA (so, fui(cso->depth.bounds_min)); SB_DATA (so, fui(cso->depth.bounds_max)); } if (cso->stencil[0].enabled) { SB_MTHD30(so, STENCIL_ENABLE(0), 3); SB_DATA (so, 1); SB_DATA (so, cso->stencil[0].writemask); SB_DATA (so, nvgl_comparison_op(cso->stencil[0].func)); SB_MTHD30(so, STENCIL_FUNC_MASK(0), 4); SB_DATA (so, cso->stencil[0].valuemask); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].fail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zfail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[0].zpass_op)); } else { SB_MTHD30(so, STENCIL_ENABLE(0), 2); SB_DATA (so, 0); SB_DATA (so, 0x000000ff); } if (cso->stencil[1].enabled) { SB_MTHD30(so, STENCIL_ENABLE(1), 3); SB_DATA (so, 1); SB_DATA (so, cso->stencil[1].writemask); SB_DATA (so, nvgl_comparison_op(cso->stencil[1].func)); SB_MTHD30(so, STENCIL_FUNC_MASK(1), 4); SB_DATA (so, cso->stencil[1].valuemask); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].fail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zfail_op)); SB_DATA (so, nvgl_stencil_op(cso->stencil[1].zpass_op)); } else { SB_MTHD30(so, STENCIL_ENABLE(1), 1); SB_DATA (so, 0); } SB_MTHD30(so, ALPHA_FUNC_ENABLE, 3); SB_DATA (so, cso->alpha.enabled ? 1 : 0); SB_DATA (so, nvgl_comparison_op(cso->alpha.func)); SB_DATA (so, float_to_ubyte(cso->alpha.ref_value)); return so; }
static void * nv40_sampler_state_create(struct pipe_context *pipe, const struct pipe_sampler_state *cso) { struct nv40_sampler_state *ps; uint32_t filter = 0; ps = MALLOC(sizeof(struct nv40_sampler_state)); ps->fmt = 0; if (!cso->normalized_coords) ps->fmt |= NV40TCL_TEX_FORMAT_RECT; ps->wrap = ((wrap_mode(cso->wrap_s) << NV40TCL_TEX_WRAP_S_SHIFT) | (wrap_mode(cso->wrap_t) << NV40TCL_TEX_WRAP_T_SHIFT) | (wrap_mode(cso->wrap_r) << NV40TCL_TEX_WRAP_R_SHIFT)); ps->en = 0; if (cso->max_anisotropy >= 2.0) { /* no idea, binary driver sets it, works without it.. meh.. */ ps->wrap |= (1 << 5); if (cso->max_anisotropy >= 16.0) { ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; } else if (cso->max_anisotropy >= 12.0) { ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; } else if (cso->max_anisotropy >= 10.0) { ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; } else if (cso->max_anisotropy >= 8.0) { ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; } else if (cso->max_anisotropy >= 6.0) { ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; } else if (cso->max_anisotropy >= 4.0) { ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; } else { ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; } } switch (cso->mag_img_filter) { case PIPE_TEX_FILTER_LINEAR: filter |= NV40TCL_TEX_FILTER_MAG_LINEAR; break; case PIPE_TEX_FILTER_NEAREST: default: filter |= NV40TCL_TEX_FILTER_MAG_NEAREST; break; } switch (cso->min_img_filter) { case PIPE_TEX_FILTER_LINEAR: switch (cso->min_mip_filter) { case PIPE_TEX_MIPFILTER_NEAREST: filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST; break; case PIPE_TEX_MIPFILTER_LINEAR: filter |= NV40TCL_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR; break; case PIPE_TEX_MIPFILTER_NONE: default: filter |= NV40TCL_TEX_FILTER_MIN_LINEAR; break; } break; case PIPE_TEX_FILTER_NEAREST: default: switch (cso->min_mip_filter) { case PIPE_TEX_MIPFILTER_NEAREST: filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST; break; case PIPE_TEX_MIPFILTER_LINEAR: filter |= NV40TCL_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR; break; case PIPE_TEX_MIPFILTER_NONE: default: filter |= NV40TCL_TEX_FILTER_MIN_NEAREST; break; } break; } ps->filt = filter; { float limit; limit = CLAMP(cso->lod_bias, -16.0, 15.0); ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; limit = CLAMP(cso->max_lod, 0.0, 15.0); ps->en |= (int)(limit * 256.0) << 7; limit = CLAMP(cso->min_lod, 0.0, 15.0); ps->en |= (int)(limit * 256.0) << 19; } if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { switch (cso->compare_func) { case PIPE_FUNC_NEVER: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NEVER; break; case PIPE_FUNC_GREATER: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GREATER; break; case PIPE_FUNC_EQUAL: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_EQUAL; break; case PIPE_FUNC_GEQUAL: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_GEQUAL; break; case PIPE_FUNC_LESS: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LESS; break; case PIPE_FUNC_NOTEQUAL: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_NOTEQUAL; break; case PIPE_FUNC_LEQUAL: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_LEQUAL; break; case PIPE_FUNC_ALWAYS: ps->wrap |= NV40TCL_TEX_WRAP_RCOMP_ALWAYS; break; default: break; } } ps->bcol = ((float_to_ubyte(cso->border_color[3]) << 24) | (float_to_ubyte(cso->border_color[0]) << 16) | (float_to_ubyte(cso->border_color[1]) << 8) | (float_to_ubyte(cso->border_color[2]) << 0)); return (void *)ps; }
static void logicop_quad(struct quad_stage *qs, float (*quadColor)[4], float (*dest)[4]) { struct softpipe_context *softpipe = qs->softpipe; ubyte src[4][4], dst[4][4], res[4][4]; uint *src4 = (uint *) src; uint *dst4 = (uint *) dst; uint *res4 = (uint *) res; uint j; /* convert to ubyte */ for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */ dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */ dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */ dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */ dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */ src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */ src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */ src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */ src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */ } switch (softpipe->blend->logicop_func) { case PIPE_LOGICOP_CLEAR: for (j = 0; j < 4; j++) res4[j] = 0; break; case PIPE_LOGICOP_NOR: for (j = 0; j < 4; j++) res4[j] = ~(src4[j] | dst4[j]); break; case PIPE_LOGICOP_AND_INVERTED: for (j = 0; j < 4; j++) res4[j] = ~src4[j] & dst4[j]; break; case PIPE_LOGICOP_COPY_INVERTED: for (j = 0; j < 4; j++) res4[j] = ~src4[j]; break; case PIPE_LOGICOP_AND_REVERSE: for (j = 0; j < 4; j++) res4[j] = src4[j] & ~dst4[j]; break; case PIPE_LOGICOP_INVERT: for (j = 0; j < 4; j++) res4[j] = ~dst4[j]; break; case PIPE_LOGICOP_XOR: for (j = 0; j < 4; j++) res4[j] = dst4[j] ^ src4[j]; break; case PIPE_LOGICOP_NAND: for (j = 0; j < 4; j++) res4[j] = ~(src4[j] & dst4[j]); break; case PIPE_LOGICOP_AND: for (j = 0; j < 4; j++) res4[j] = src4[j] & dst4[j]; break; case PIPE_LOGICOP_EQUIV: for (j = 0; j < 4; j++) res4[j] = ~(src4[j] ^ dst4[j]); break; case PIPE_LOGICOP_NOOP: for (j = 0; j < 4; j++) res4[j] = dst4[j]; break; case PIPE_LOGICOP_OR_INVERTED: for (j = 0; j < 4; j++) res4[j] = ~src4[j] | dst4[j]; break; case PIPE_LOGICOP_COPY: for (j = 0; j < 4; j++) res4[j] = src4[j]; break; case PIPE_LOGICOP_OR_REVERSE: for (j = 0; j < 4; j++) res4[j] = src4[j] | ~dst4[j]; break; case PIPE_LOGICOP_OR: for (j = 0; j < 4; j++) res4[j] = src4[j] | dst4[j]; break; case PIPE_LOGICOP_SET: for (j = 0; j < 4; j++) res4[j] = ~0; break; default: assert(0); } for (j = 0; j < 4; j++) { quadColor[j][0] = ubyte_to_float(res[j][0]); quadColor[j][1] = ubyte_to_float(res[j][1]); quadColor[j][2] = ubyte_to_float(res[j][2]); quadColor[j][3] = ubyte_to_float(res[j][3]); } }
bool radv_format_pack_clear_color(VkFormat format, uint32_t clear_vals[2], VkClearColorValue *value) { uint8_t r = 0, g = 0, b = 0, a = 0; const struct vk_format_description *desc = vk_format_description(format); if (vk_format_get_component_bits(format, VK_FORMAT_COLORSPACE_RGB, 0) <= 8) { if (desc->colorspace == VK_FORMAT_COLORSPACE_RGB) { r = float_to_ubyte(value->float32[0]); g = float_to_ubyte(value->float32[1]); b = float_to_ubyte(value->float32[2]); a = float_to_ubyte(value->float32[3]); } else if (desc->colorspace == VK_FORMAT_COLORSPACE_SRGB) { r = util_format_linear_float_to_srgb_8unorm(value->float32[0]); g = util_format_linear_float_to_srgb_8unorm(value->float32[1]); b = util_format_linear_float_to_srgb_8unorm(value->float32[2]); a = float_to_ubyte(value->float32[3]); } } switch (format) { case VK_FORMAT_R8_UNORM: case VK_FORMAT_R8_SRGB: clear_vals[0] = r; clear_vals[1] = 0; break; case VK_FORMAT_R8G8_UNORM: case VK_FORMAT_R8G8_SRGB: clear_vals[0] = r | g << 8; clear_vals[1] = 0; break; case VK_FORMAT_R8G8B8A8_SRGB: case VK_FORMAT_R8G8B8A8_UNORM: clear_vals[0] = r | g << 8 | b << 16 | a << 24; clear_vals[1] = 0; break; case VK_FORMAT_B8G8R8A8_SRGB: case VK_FORMAT_B8G8R8A8_UNORM: clear_vals[0] = b | g << 8 | r << 16 | a << 24; clear_vals[1] = 0; break; case VK_FORMAT_A8B8G8R8_UNORM_PACK32: case VK_FORMAT_A8B8G8R8_SRGB_PACK32: clear_vals[0] = r | g << 8 | b << 16 | a << 24; clear_vals[1] = 0; break; case VK_FORMAT_R8_UINT: clear_vals[0] = value->uint32[0] & 0xff; clear_vals[1] = 0; break; case VK_FORMAT_R16_UINT: clear_vals[0] = value->uint32[0] & 0xffff; clear_vals[1] = 0; break; case VK_FORMAT_R8G8_UINT: clear_vals[0] = value->uint32[0] & 0xff; clear_vals[0] |= (value->uint32[1] & 0xff) << 8; clear_vals[1] = 0; break; case VK_FORMAT_R8G8B8A8_UINT: clear_vals[0] = value->uint32[0] & 0xff; clear_vals[0] |= (value->uint32[1] & 0xff) << 8; clear_vals[0] |= (value->uint32[2] & 0xff) << 16; clear_vals[0] |= (value->uint32[3] & 0xff) << 24; clear_vals[1] = 0; break; case VK_FORMAT_A8B8G8R8_UINT_PACK32: clear_vals[0] = value->uint32[0] & 0xff; clear_vals[0] |= (value->uint32[1] & 0xff) << 8; clear_vals[0] |= (value->uint32[2] & 0xff) << 16; clear_vals[0] |= (value->uint32[3] & 0xff) << 24; clear_vals[1] = 0; break; case VK_FORMAT_R16G16_UINT: clear_vals[0] = value->uint32[0] & 0xffff; clear_vals[0] |= (value->uint32[1] & 0xffff) << 16; clear_vals[1] = 0; break; case VK_FORMAT_R16G16B16A16_UINT: clear_vals[0] = value->uint32[0] & 0xffff; clear_vals[0] |= (value->uint32[1] & 0xffff) << 16; clear_vals[1] = value->uint32[2] & 0xffff; clear_vals[1] |= (value->uint32[3] & 0xffff) << 16; break; case VK_FORMAT_R32_UINT: clear_vals[0] = value->uint32[0]; clear_vals[1] = 0; break; case VK_FORMAT_R32G32_UINT: clear_vals[0] = value->uint32[0]; clear_vals[1] = value->uint32[1]; break; case VK_FORMAT_R32_SINT: clear_vals[0] = value->int32[0]; clear_vals[1] = 0; break; case VK_FORMAT_R16_SFLOAT: clear_vals[0] = util_float_to_half(value->float32[0]); clear_vals[1] = 0; break; case VK_FORMAT_R16G16_SFLOAT: clear_vals[0] = util_float_to_half(value->float32[0]); clear_vals[0] |= (uint32_t)util_float_to_half(value->float32[1]) << 16; clear_vals[1] = 0; break; case VK_FORMAT_R16G16B16A16_SFLOAT: clear_vals[0] = util_float_to_half(value->float32[0]); clear_vals[0] |= (uint32_t)util_float_to_half(value->float32[1]) << 16; clear_vals[1] = util_float_to_half(value->float32[2]); clear_vals[1] |= (uint32_t)util_float_to_half(value->float32[3]) << 16; break; case VK_FORMAT_R16_UNORM: clear_vals[0] = ((uint16_t)util_iround(CLAMP(value->float32[0], 0.0f, 1.0f) * 0xffff)) & 0xffff; clear_vals[1] = 0; break; case VK_FORMAT_R16G16_UNORM: clear_vals[0] = ((uint16_t)util_iround(CLAMP(value->float32[0], 0.0f, 1.0f) * 0xffff)) & 0xffff; clear_vals[0] |= ((uint16_t)util_iround(CLAMP(value->float32[1], 0.0f, 1.0f) * 0xffff)) << 16; clear_vals[1] = 0; break; case VK_FORMAT_R16G16B16A16_UNORM: clear_vals[0] = ((uint16_t)util_iround(CLAMP(value->float32[0], 0.0f, 1.0f) * 0xffff)) & 0xffff; clear_vals[0] |= ((uint16_t)util_iround(CLAMP(value->float32[1], 0.0f, 1.0f) * 0xffff)) << 16; clear_vals[1] = ((uint16_t)util_iround(CLAMP(value->float32[2], 0.0f, 1.0f) * 0xffff)) & 0xffff; clear_vals[1] |= ((uint16_t)util_iround(CLAMP(value->float32[3], 0.0f, 1.0f) * 0xffff)) << 16; break; case VK_FORMAT_A2B10G10R10_UNORM_PACK32: /* TODO */ return false; case VK_FORMAT_R32G32_SFLOAT: clear_vals[0] = fui(value->float32[0]); clear_vals[1] = fui(value->float32[1]); break; case VK_FORMAT_R32_SFLOAT: clear_vals[1] = 0; clear_vals[0] = fui(value->float32[0]); break; default: fprintf(stderr, "failed to fast clear %d\n", format); return false; } return true; }