/** * Run the shader on all blocks in a tile. This is used when a tile is * completely contained inside a triangle. * This is a bin command called during bin processing. */ static void lp_rast_shade_tile(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; const struct lp_rast_shader_inputs *inputs = arg.shade_tile; const struct lp_rast_state *state; struct lp_fragment_shader_variant *variant; const unsigned tile_x = task->x, tile_y = task->y; unsigned x, y; if (inputs->disable) { /* This command was partially binned and has been disabled */ return; } LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); state = task->state; assert(state); if (!state) { return; } variant = state->variant; /* render the whole 64x64 tile in 4x4 chunks */ for (y = 0; y < task->height; y += 4){ for (x = 0; x < task->width; x += 4) { uint8_t *color[PIPE_MAX_COLOR_BUFS]; unsigned stride[PIPE_MAX_COLOR_BUFS]; uint8_t *depth = NULL; unsigned depth_stride = 0; unsigned i; /* color buffer */ for (i = 0; i < scene->fb.nr_cbufs; i++){ if (scene->fb.cbufs[i]) { stride[i] = scene->cbufs[i].stride; color[i] = lp_rast_get_color_block_pointer(task, i, tile_x + x, tile_y + y, inputs->layer); } else { stride[i] = 0; color[i] = NULL; } } /* depth buffer */ if (scene->zsbuf.map) { depth = lp_rast_get_depth_block_pointer(task, tile_x + x, tile_y + y, inputs->layer); depth_stride = scene->zsbuf.stride; } /* Propagate non-interpolated raster state. */ task->thread_data.raster_state.viewport_index = inputs->viewport_index; /* run shader on 4x4 block */ BEGIN_JIT_CALL(state, task); variant->jit_function[RAST_WHOLE]( &state->jit_context, tile_x + x, tile_y + y, inputs->frontfacing, GET_A0(inputs), GET_DADX(inputs), GET_DADY(inputs), color, depth, 0xffff, &task->thread_data, stride, depth_stride); END_JIT_CALL(); } } }
/** * Called during state validation when LP_NEW_SAMPLER_VIEW is set. */ void lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, unsigned num, struct pipe_sampler_view **views) { unsigned i; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); assert(num <= PIPE_MAX_SAMPLERS); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { struct pipe_resource *tex = view->texture; struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex); struct lp_jit_texture *jit_tex; jit_tex = &setup->fs.current.jit_context.textures[i]; jit_tex->width = tex->width0; jit_tex->height = tex->height0; jit_tex->depth = tex->depth0; jit_tex->first_level = view->u.tex.first_level; jit_tex->last_level = tex->last_level; /* We're referencing the texture's internal data, so save a * reference to it. */ pipe_resource_reference(&setup->fs.current_tex[i], tex); if (!lp_tex->dt) { /* regular texture - setup array of mipmap level pointers */ int j; for (j = view->u.tex.first_level; j <= tex->last_level; j++) { jit_tex->data[j] = llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, LP_TEX_LAYOUT_LINEAR); jit_tex->row_stride[j] = lp_tex->row_stride[j]; jit_tex->img_stride[j] = lp_tex->img_stride[j]; if ((LP_PERF & PERF_TEX_MEM) || !jit_tex->data[j]) { /* out of memory - use dummy tile memory */ jit_tex->data[j] = lp_dummy_tile; jit_tex->width = TILE_SIZE/8; jit_tex->height = TILE_SIZE/8; jit_tex->depth = 1; jit_tex->first_level = 0; jit_tex->last_level = 0; jit_tex->row_stride[j] = 0; jit_tex->img_stride[j] = 0; } } } else { /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); struct sw_winsys *winsys = screen->winsys; jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_TRANSFER_READ); jit_tex->row_stride[0] = lp_tex->row_stride[0]; jit_tex->img_stride[0] = lp_tex->img_stride[0]; assert(jit_tex->data[0]); } } } setup->dirty |= LP_SETUP_NEW_FS; }
/** * Clear the rasterizer's current z/stencil tile. * This is a bin command called during bin processing. * Clear commands always clear all bound layers. */ static void lp_rast_clear_zstencil(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; uint64_t clear_value64 = arg.clear_zstencil.value; uint64_t clear_mask64 = arg.clear_zstencil.mask; uint32_t clear_value = (uint32_t) clear_value64; uint32_t clear_mask = (uint32_t) clear_mask64; const unsigned height = task->height; const unsigned width = task->width; const unsigned dst_stride = scene->zsbuf.stride; uint8_t *dst; unsigned i, j; unsigned block_size; LP_DBG(DEBUG_RAST, "%s: value=0x%08x, mask=0x%08x\n", __FUNCTION__, clear_value, clear_mask); /* * Clear the area of the depth/depth buffer matching this tile. */ if (scene->fb.zsbuf) { unsigned layer; uint8_t *dst_layer = lp_rast_get_depth_tile_pointer(task, LP_TEX_USAGE_READ_WRITE); block_size = util_format_get_blocksize(scene->fb.zsbuf->format); clear_value &= clear_mask; for (layer = 0; layer <= scene->fb_max_layer; layer++) { dst = dst_layer; switch (block_size) { case 1: assert(clear_mask == 0xff); memset(dst, (uint8_t) clear_value, height * width); break; case 2: if (clear_mask == 0xffff) { for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) *row++ = (uint16_t) clear_value; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) { uint16_t tmp = ~clear_mask & *row; *row++ = clear_value | tmp; } dst += dst_stride; } } break; case 4: if (clear_mask == 0xffffffff) { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst; for (j = 0; j < width; j++) *row++ = clear_value; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst; for (j = 0; j < width; j++) { uint32_t tmp = ~clear_mask & *row; *row++ = clear_value | tmp; } dst += dst_stride; } } break; case 8: clear_value64 &= clear_mask64; if (clear_mask64 == 0xffffffffffULL) { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst; for (j = 0; j < width; j++) *row++ = clear_value64; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint64_t *row = (uint64_t *)dst; for (j = 0; j < width; j++) { uint64_t tmp = ~clear_mask64 & *row; *row++ = clear_value64 | tmp; } dst += dst_stride; } } break; default: assert(0); break; } dst_layer += scene->zsbuf.layer_stride; } } }
static boolean begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = setup->scene; boolean need_zsload = FALSE; boolean ok; unsigned i, j; assert(scene); assert(scene->fence == NULL); /* Always create a fence: */ scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); if (!scene->fence) return FALSE; /* Initialize the bin flags and x/y coords: */ for (i = 0; i < scene->tiles_x; i++) { for (j = 0; j < scene->tiles_y; j++) { scene->tile[i][j].x = i; scene->tile[i][j].y = j; } } ok = try_update_scene_state(setup); if (!ok) return FALSE; if (setup->fb.zsbuf && ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) need_zsload = TRUE; LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", need_zsload ? "clear": "load"); if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) { ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_COLOR, setup->clear.color ); if (!ok) return FALSE; } } if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { if (!need_zsload) scene->has_depthstencil_clear = TRUE; ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( setup->clear.zsvalue, setup->clear.zsmask)); if (!ok) return FALSE; } } if (setup->active_query) { ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_BEGIN_QUERY, lp_rast_arg_query(setup->active_query) ); if (!ok) return FALSE; } setup->clear.flags = 0; setup->clear.zsmask = 0; setup->clear.zsvalue = 0; LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); 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) { uint32_t zmask = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; uint32_t smask = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; zsvalue = util_pack_z_stencil(setup->fb.zsbuf->format, depth, stencil); zsmask = util_pack_mask_z_stencil(setup->fb.zsbuf->format, zmask, smask); zsvalue &= zsmask; } 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 setup->clear.color.clear_color); } } return TRUE; }
/** * Called during state validation when LP_NEW_SAMPLER_VIEW is set. */ void lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, unsigned num, struct pipe_sampler_view **views) { unsigned i; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { struct pipe_resource *tex = view->texture; struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex); struct lp_jit_texture *jit_tex; jit_tex = &setup->fs.current.jit_context.textures[i]; jit_tex->width = tex->width0; jit_tex->height = tex->height0; jit_tex->first_level = view->u.tex.first_level; jit_tex->last_level = tex->last_level; if (tex->target == PIPE_TEXTURE_3D) { jit_tex->depth = tex->depth0; } else { jit_tex->depth = tex->array_size; } /* We're referencing the texture's internal data, so save a * reference to it. */ pipe_resource_reference(&setup->fs.current_tex[i], tex); if (!lp_tex->dt) { /* regular texture - setup array of mipmap level offsets */ void *mip_ptr; int j; /* * XXX this is messed up we don't want to accidentally trigger * tiled->linear conversion for levels we don't need. * So ask for first_level data (which will allocate all levels) * then if successful get base ptr. */ mip_ptr = llvmpipe_get_texture_image_all(lp_tex, view->u.tex.first_level, LP_TEX_USAGE_READ, LP_TEX_LAYOUT_LINEAR); if ((LP_PERF & PERF_TEX_MEM) || !mip_ptr) { /* out of memory - use dummy tile memory */ jit_tex->base = lp_dummy_tile; jit_tex->width = TILE_SIZE/8; jit_tex->height = TILE_SIZE/8; jit_tex->depth = 1; jit_tex->first_level = 0; jit_tex->last_level = 0; } else { jit_tex->base = lp_tex->linear_img.data; } for (j = view->u.tex.first_level; j <= tex->last_level; j++) { mip_ptr = llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, LP_TEX_LAYOUT_LINEAR); jit_tex->mip_offsets[j] = (uint8_t *)mip_ptr - (uint8_t *)jit_tex->base; /* * could get mip offset directly but need call above to * invoke tiled->linear conversion. */ assert(lp_tex->linear_mip_offsets[j] == jit_tex->mip_offsets[j]); jit_tex->row_stride[j] = lp_tex->row_stride[j]; jit_tex->img_stride[j] = lp_tex->img_stride[j]; if (jit_tex->base == lp_dummy_tile) { /* out of memory - use dummy tile memory */ jit_tex->mip_offsets[j] = 0; jit_tex->row_stride[j] = 0; jit_tex->img_stride[j] = 0; } } } else { /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen); struct sw_winsys *winsys = screen->winsys; jit_tex->base = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_TRANSFER_READ); jit_tex->row_stride[0] = lp_tex->row_stride[0]; jit_tex->img_stride[0] = lp_tex->img_stride[0]; jit_tex->mip_offsets[0] = 0; assert(jit_tex->base); } } } setup->dirty |= LP_SETUP_NEW_FS; }
/** * Clear the rasterizer's current z/stencil tile. * This is a bin command called during bin processing. */ static void lp_rast_clear_zstencil(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; uint32_t clear_value = arg.clear_zstencil.value; uint32_t clear_mask = arg.clear_zstencil.mask; const unsigned height = TILE_SIZE / TILE_VECTOR_HEIGHT; const unsigned width = TILE_SIZE * TILE_VECTOR_HEIGHT; const unsigned block_size = scene->zsbuf.blocksize; const unsigned dst_stride = scene->zsbuf.stride * TILE_VECTOR_HEIGHT; uint8_t *dst; unsigned i, j; LP_DBG(DEBUG_RAST, "%s: value=0x%08x, mask=0x%08x\n", __FUNCTION__, clear_value, clear_mask); /* * Clear the aera of the swizzled depth/depth buffer matching this tile, in * stripes of TILE_VECTOR_HEIGHT x TILE_SIZE at a time. * * The swizzled depth format is such that the depths for * TILE_VECTOR_HEIGHT x TILE_VECTOR_WIDTH pixels have consecutive offsets. */ dst = task->depth_tile; clear_value &= clear_mask; switch (block_size) { case 1: assert(clear_mask == 0xff); memset(dst, (uint8_t) clear_value, height * width); break; case 2: if (clear_mask == 0xffff) { for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) *row++ = (uint16_t) clear_value; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint16_t *row = (uint16_t *)dst; for (j = 0; j < width; j++) { uint16_t tmp = ~clear_mask & *row; *row++ = clear_value | tmp; } dst += dst_stride; } } break; case 4: if (clear_mask == 0xffffffff) { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst; for (j = 0; j < width; j++) *row++ = clear_value; dst += dst_stride; } } else { for (i = 0; i < height; i++) { uint32_t *row = (uint32_t *)dst; for (j = 0; j < width; j++) { uint32_t tmp = ~clear_mask & *row; *row++ = clear_value | tmp; } dst += dst_stride; } } break; default: assert(0); break; } }
/** * Clear the rasterizer's current color tile. * This is a bin command called during bin processing. */ static void lp_rast_clear_color(struct lp_rasterizer_task *task, const union lp_rast_cmd_arg arg) { const struct lp_scene *scene = task->scene; if (scene->fb.nr_cbufs) { unsigned i; union util_color uc; if (util_format_is_pure_integer(scene->fb.cbufs[0]->format)) { /* * We expect int/uint clear values here, though some APIs * might disagree (but in any case util_pack_color() * couldn't handle it)... */ LP_DBG(DEBUG_RAST, "%s pure int 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__, arg.clear_color.ui[0], arg.clear_color.ui[1], arg.clear_color.ui[2], arg.clear_color.ui[3]); for (i = 0; i < scene->fb.nr_cbufs; i++) { enum pipe_format format = scene->fb.cbufs[i]->format; if (util_format_is_pure_sint(format)) { util_format_write_4i(format, arg.clear_color.i, 0, &uc, 0, 0, 0, 1, 1); } else { assert(util_format_is_pure_uint(format)); util_format_write_4ui(format, arg.clear_color.ui, 0, &uc, 0, 0, 0, 1, 1); } util_fill_rect(scene->cbufs[i].map, scene->fb.cbufs[i]->format, scene->cbufs[i].stride, task->x, task->y, TILE_SIZE, TILE_SIZE, &uc); } } else { uint8_t clear_color[4]; for (i = 0; i < 4; ++i) { clear_color[i] = float_to_ubyte(arg.clear_color.f[i]); } LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__, clear_color[0], clear_color[1], clear_color[2], clear_color[3]); for (i = 0; i < scene->fb.nr_cbufs; i++) { util_pack_color(arg.clear_color.f, scene->fb.cbufs[i]->format, &uc); util_fill_rect(scene->cbufs[i].map, scene->fb.cbufs[i]->format, scene->cbufs[i].stride, task->x, task->y, TILE_SIZE, TILE_SIZE, &uc); } } } LP_COUNT(nr_color_tile_clear); }
/** * Called during state validation when LP_NEW_SAMPLER_VIEW is set. */ void lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, unsigned num, struct pipe_sampler_view **views) { unsigned i, max_tex_num; LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); max_tex_num = MAX2(num, setup->fs.current_tex_num); for (i = 0; i < max_tex_num; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { struct pipe_resource *res = view->texture; struct llvmpipe_resource *lp_tex = llvmpipe_resource(res); struct lp_jit_texture *jit_tex; jit_tex = &setup->fs.current.jit_context.textures[i]; /* We're referencing the texture's internal data, so save a * reference to it. */ pipe_resource_reference(&setup->fs.current_tex[i], res); if (!lp_tex->dt) { /* regular texture - setup array of mipmap level offsets */ int j; unsigned first_level = 0; unsigned last_level = 0; if (llvmpipe_resource_is_texture(res)) { first_level = view->u.tex.first_level; last_level = view->u.tex.last_level; assert(first_level <= last_level); assert(last_level <= res->last_level); jit_tex->base = lp_tex->tex_data; } else { jit_tex->base = lp_tex->data; } if (LP_PERF & PERF_TEX_MEM) { /* use dummy tile memory */ jit_tex->base = lp_dummy_tile; jit_tex->width = TILE_SIZE/8; jit_tex->height = TILE_SIZE/8; jit_tex->depth = 1; jit_tex->first_level = 0; jit_tex->last_level = 0; jit_tex->mip_offsets[0] = 0; jit_tex->row_stride[0] = 0; jit_tex->img_stride[0] = 0; } else { jit_tex->width = res->width0; jit_tex->height = res->height0; jit_tex->depth = res->depth0; jit_tex->first_level = first_level; jit_tex->last_level = last_level; if (llvmpipe_resource_is_texture(res)) { for (j = first_level; j <= last_level; j++) { jit_tex->mip_offsets[j] = lp_tex->mip_offsets[j]; jit_tex->row_stride[j] = lp_tex->row_stride[j]; jit_tex->img_stride[j] = lp_tex->img_stride[j]; } if (res->target == PIPE_TEXTURE_1D_ARRAY || res->target == PIPE_TEXTURE_2D_ARRAY || res->target == PIPE_TEXTURE_CUBE || res->target == PIPE_TEXTURE_CUBE_ARRAY) { /* * For array textures, we don't have first_layer, instead * adjust last_layer (stored as depth) plus the mip level offsets * (as we have mip-first layout can't just adjust base ptr). * XXX For mip levels, could do something similar. */ jit_tex->depth = view->u.tex.last_layer - view->u.tex.first_layer + 1; for (j = first_level; j <= last_level; j++) { jit_tex->mip_offsets[j] += view->u.tex.first_layer * lp_tex->img_stride[j]; } if (view->target == PIPE_TEXTURE_CUBE || view->target == PIPE_TEXTURE_CUBE_ARRAY) { assert(jit_tex->depth % 6 == 0); } assert(view->u.tex.first_layer <= view->u.tex.last_layer); assert(view->u.tex.last_layer < res->array_size); } } else { /* * For buffers, we don't have "offset", instead adjust * the size (stored as width) plus the base pointer. */ unsigned view_blocksize = util_format_get_blocksize(view->format); /* probably don't really need to fill that out */ jit_tex->mip_offsets[0] = 0; jit_tex->row_stride[0] = 0; jit_tex->img_stride[0] = 0; /* everything specified in number of elements here. */ jit_tex->width = view->u.buf.size / view_blocksize; jit_tex->base = (uint8_t *)jit_tex->base + view->u.buf.offset; /* XXX Unsure if we need to sanitize parameters? */ assert(view->u.buf.offset + view->u.buf.size <= res->width0); } } } else { /* display target texture/surface */ /* * XXX: Where should this be unmapped? */ struct llvmpipe_screen *screen = llvmpipe_screen(res->screen); struct sw_winsys *winsys = screen->winsys; jit_tex->base = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_TRANSFER_READ); jit_tex->row_stride[0] = lp_tex->row_stride[0]; jit_tex->img_stride[0] = lp_tex->img_stride[0]; jit_tex->mip_offsets[0] = 0; jit_tex->width = res->width0; jit_tex->height = res->height0; jit_tex->depth = res->depth0; jit_tex->first_level = jit_tex->last_level = 0; assert(jit_tex->base); } } else { pipe_resource_reference(&setup->fs.current_tex[i], NULL); } } setup->fs.current_tex_num = num; setup->dirty |= LP_SETUP_NEW_FS; }
static boolean lp_setup_try_clear_zs(struct lp_setup_context *setup, double depth, unsigned stencil, unsigned flags) { uint64_t zsmask = 0; uint64_t zsvalue = 0; uint32_t zmask32; uint8_t smask8; enum pipe_format format = setup->fb.zsbuf->format; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); zmask32 = (flags & PIPE_CLEAR_DEPTH) ? ~0 : 0; smask8 = (flags & PIPE_CLEAR_STENCIL) ? ~0 : 0; zsvalue = util_pack64_z_stencil(format, depth, stencil); zsmask = util_pack64_mask_z_stencil(format, zmask32, smask8); zsvalue &= zsmask; if (format == PIPE_FORMAT_Z24X8_UNORM || format == PIPE_FORMAT_X8Z24_UNORM) { /* * Make full mask if there's "X" bits so we can do full * clear (without rmw). */ uint32_t zsmask_full = 0; zsmask_full = util_pack_mask_z_stencil(format, ~0, ~0); zsmask |= ~zsmask_full; } 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 (!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; setup->clear.zsmask |= zsmask; setup->clear.zsvalue = (setup->clear.zsvalue & ~zsmask) | (zsvalue & zsmask); } return TRUE; }
/* * Try to clear one color buffer of the attached fb, either by binning a clear * command or queuing up the clear for later (when binning is started). */ static boolean lp_setup_try_clear_color_buffer(struct lp_setup_context *setup, const union pipe_color_union *color, unsigned cbuf) { union lp_rast_cmd_arg clearrb_arg; union util_color uc; enum pipe_format format = setup->fb.cbufs[cbuf]->format; LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); if (util_format_is_pure_integer(format)) { /* * We expect int/uint clear values here, though some APIs * might disagree (but in any case util_pack_color() * couldn't handle it)... */ if (util_format_is_pure_sint(format)) { util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1); } else { assert(util_format_is_pure_uint(format)); util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1); } } else { util_pack_color(color->f, format, &uc); } 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. */ struct lp_rast_clear_rb *cc_scene = (struct lp_rast_clear_rb *) lp_scene_alloc_aligned(scene, sizeof(struct lp_rast_clear_rb), 8); if (!cc_scene) { return FALSE; } cc_scene->cbuf = cbuf; cc_scene->color_val = uc; clearrb_arg.clear_rb = cc_scene; if (!lp_scene_bin_everywhere(scene, LP_RAST_OP_CLEAR_COLOR, clearrb_arg)) 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__ ); assert(PIPE_CLEAR_COLOR0 == (1 << 2)); setup->clear.flags |= 1 << (cbuf + 2); setup->clear.color_val[cbuf] = uc; } return TRUE; }
static boolean begin_binning( struct lp_setup_context *setup ) { struct lp_scene *scene = setup->scene; boolean need_zsload = FALSE; boolean ok; assert(scene); assert(scene->fence == NULL); /* Always create a fence: */ scene->fence = lp_fence_create(MAX2(1, setup->num_threads)); if (!scene->fence) return FALSE; ok = try_update_scene_state(setup); if (!ok) return FALSE; if (setup->fb.zsbuf && ((setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) && util_format_is_depth_and_stencil(setup->fb.zsbuf->format)) need_zsload = TRUE; LP_DBG(DEBUG_SETUP, "%s color clear bufs: %x depth: %s\n", __FUNCTION__, setup->clear.flags >> 2, need_zsload ? "clear": "load"); if (setup->clear.flags & PIPE_CLEAR_COLOR) { unsigned cbuf; for (cbuf = 0; cbuf < setup->fb.nr_cbufs; cbuf++) { assert(PIPE_CLEAR_COLOR0 == 1 << 2); if (setup->clear.flags & (1 << (2 + cbuf))) { union lp_rast_cmd_arg clearrb_arg; struct lp_rast_clear_rb *cc_scene = (struct lp_rast_clear_rb *) lp_scene_alloc(scene, sizeof(struct lp_rast_clear_rb)); if (!cc_scene) { return FALSE; } cc_scene->cbuf = cbuf; cc_scene->color_val = setup->clear.color_val[cbuf]; clearrb_arg.clear_rb = cc_scene; if (!lp_scene_bin_everywhere(scene, LP_RAST_OP_CLEAR_COLOR, clearrb_arg)) return FALSE; } } } if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) { ok = lp_scene_bin_everywhere( scene, LP_RAST_OP_CLEAR_ZSTENCIL, lp_rast_arg_clearzs( setup->clear.zsvalue, setup->clear.zsmask)); if (!ok) return FALSE; } } setup->clear.flags = 0; setup->clear.zsmask = 0; setup->clear.zsvalue = 0; scene->had_queries = !!setup->active_binned_queries; LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); return TRUE; }