vl_zscan.c revision f0819a22f3dc63d1c0dde6320babf9b7fcda15bb
1/************************************************************************** 2 * 3 * Copyright 2011 Christian König 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include <assert.h> 29 30#include <pipe/p_screen.h> 31#include <pipe/p_context.h> 32 33#include <util/u_draw.h> 34#include <util/u_sampler.h> 35#include <util/u_inlines.h> 36 37#include <tgsi/tgsi_ureg.h> 38 39#include <vl/vl_defines.h> 40#include <vl/vl_types.h> 41 42#include "vl_zscan.h" 43#include "vl_vertex_buffers.h" 44 45enum VS_OUTPUT 46{ 47 VS_O_VPOS, 48 VS_O_VTEX 49}; 50 51static void * 52create_vert_shader(struct vl_zscan *zscan) 53{ 54 struct ureg_program *shader; 55 56 struct ureg_src scale, instance; 57 struct ureg_src vrect, vpos; 58 59 struct ureg_dst tmp; 60 struct ureg_dst o_vpos, o_vtex[zscan->num_channels]; 61 62 unsigned i; 63 64 shader = ureg_create(TGSI_PROCESSOR_VERTEX); 65 if (!shader) 66 return NULL; 67 68 scale = ureg_imm2f(shader, 69 (float)BLOCK_WIDTH / zscan->buffer_width, 70 (float)BLOCK_HEIGHT / zscan->buffer_height); 71 72 instance = ureg_DECL_system_value(shader, 0, TGSI_SEMANTIC_INSTANCEID, 0); 73 74 vrect = ureg_DECL_vs_input(shader, VS_I_RECT); 75 vpos = ureg_DECL_vs_input(shader, VS_I_VPOS); 76 77 tmp = ureg_DECL_temporary(shader); 78 79 o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); 80 81 for (i = 0; i < zscan->num_channels; ++i) 82 o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i); 83 84 /* 85 * o_vpos.xy = (vpos + vrect) * scale 86 * o_vpos.zw = 1.0f 87 * 88 * tmp.xy = InstanceID / blocks_per_line 89 * tmp.x = frac(tmp.x) 90 * tmp.y = floor(tmp.y) 91 * 92 * o_vtex.x = vrect.x / blocks_per_line + tmp.x 93 * o_vtex.y = vrect.y 94 * o_vtex.z = tmp.z * blocks_per_line / blocks_total 95 */ 96 ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), vpos, vrect); 97 ureg_MUL(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(tmp), scale); 98 ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f)); 99 100 ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XZ), instance, 101 ureg_imm1f(shader, 1.0f / zscan->blocks_per_line)); 102 103 ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(tmp)); 104 ureg_FLR(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Z), ureg_src(tmp)); 105 106 for (i = 0; i < zscan->num_channels; ++i) { 107 if (i > 0) 108 ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(tmp), 109 ureg_imm1f(shader, 1.0f / (zscan->blocks_per_line * BLOCK_WIDTH))); 110 111 ureg_MAD(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_X), vrect, 112 ureg_imm1f(shader, 1.0f / zscan->blocks_per_line), ureg_src(tmp)); 113 ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Y), vrect); 114 ureg_MUL(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Z), ureg_src(tmp), 115 ureg_imm1f(shader, (float)zscan->blocks_per_line / zscan->blocks_total)); 116 } 117 118 ureg_release_temporary(shader, tmp); 119 ureg_END(shader); 120 121 return ureg_create_shader_and_destroy(shader, zscan->pipe); 122} 123 124static void * 125create_frag_shader(struct vl_zscan *zscan) 126{ 127 struct ureg_program *shader; 128 struct ureg_src vtex[zscan->num_channels]; 129 130 struct ureg_src src, scan, quant; 131 132 struct ureg_dst tmp[zscan->num_channels]; 133 struct ureg_dst fragment; 134 135 unsigned i; 136 137 shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); 138 if (!shader) 139 return NULL; 140 141 for (i = 0; i < zscan->num_channels; ++i) 142 vtex[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i, TGSI_INTERPOLATE_LINEAR); 143 144 src = ureg_DECL_sampler(shader, 0); 145 scan = ureg_DECL_sampler(shader, 1); 146 quant = ureg_DECL_sampler(shader, 2); 147 148 for (i = 0; i < zscan->num_channels; ++i) 149 tmp[i] = ureg_DECL_temporary(shader); 150 151 fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); 152 153 /* 154 * tmp.x = tex(vtex, 1) 155 * tmp.y = vtex.z 156 * fragment = tex(tmp, 0) * quant 157 */ 158 for (i = 0; i < zscan->num_channels; ++i) 159 ureg_TEX(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_X), TGSI_TEXTURE_2D, vtex[i], scan); 160 161 for (i = 0; i < zscan->num_channels; ++i) 162 ureg_MOV(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_Y), ureg_scalar(vtex[i], TGSI_SWIZZLE_Z)); 163 164 for (i = 0; i < zscan->num_channels; ++i) 165 ureg_TEX(shader, tmp[i], TGSI_TEXTURE_2D, ureg_src(tmp[i]), src); 166 167 // TODO: Fetch quant and use it 168 for (i = 0; i < zscan->num_channels; ++i) 169 ureg_MUL(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), ureg_src(tmp[i]), ureg_imm1f(shader, 1.0f)); 170 171 for (i = 0; i < zscan->num_channels; ++i) 172 ureg_release_temporary(shader, tmp[i]); 173 ureg_END(shader); 174 175 return ureg_create_shader_and_destroy(shader, zscan->pipe); 176} 177 178static bool 179init_shaders(struct vl_zscan *zscan) 180{ 181 assert(zscan); 182 183 zscan->vs = create_vert_shader(zscan); 184 if (!zscan->vs) 185 goto error_vs; 186 187 zscan->fs = create_frag_shader(zscan); 188 if (!zscan->fs) 189 goto error_fs; 190 191 return true; 192 193error_fs: 194 zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs); 195 196error_vs: 197 return false; 198} 199 200static void 201cleanup_shaders(struct vl_zscan *zscan) 202{ 203 assert(zscan); 204 205 zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs); 206 zscan->pipe->delete_fs_state(zscan->pipe, zscan->fs); 207} 208 209static bool 210init_state(struct vl_zscan *zscan) 211{ 212 struct pipe_blend_state blend; 213 struct pipe_rasterizer_state rs_state; 214 struct pipe_sampler_state sampler; 215 unsigned i; 216 217 assert(zscan); 218 219 memset(&rs_state, 0, sizeof(rs_state)); 220 rs_state.gl_rasterization_rules = false; 221 zscan->rs_state = zscan->pipe->create_rasterizer_state(zscan->pipe, &rs_state); 222 if (!zscan->rs_state) 223 goto error_rs_state; 224 225 memset(&blend, 0, sizeof blend); 226 227 blend.independent_blend_enable = 0; 228 blend.rt[0].blend_enable = 0; 229 blend.rt[0].rgb_func = PIPE_BLEND_ADD; 230 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 231 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 232 blend.rt[0].alpha_func = PIPE_BLEND_ADD; 233 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 234 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 235 blend.logicop_enable = 0; 236 blend.logicop_func = PIPE_LOGICOP_CLEAR; 237 /* Needed to allow color writes to FB, even if blending disabled */ 238 blend.rt[0].colormask = PIPE_MASK_RGBA; 239 blend.dither = 0; 240 zscan->blend = zscan->pipe->create_blend_state(zscan->pipe, &blend); 241 if (!zscan->blend) 242 goto error_blend; 243 244 for (i = 0; i < 3; ++i) { 245 memset(&sampler, 0, sizeof(sampler)); 246 sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; 247 sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; 248 sampler.wrap_r = PIPE_TEX_WRAP_REPEAT; 249 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 250 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 251 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 252 sampler.compare_mode = PIPE_TEX_COMPARE_NONE; 253 sampler.compare_func = PIPE_FUNC_ALWAYS; 254 sampler.normalized_coords = 1; 255 zscan->samplers[i] = zscan->pipe->create_sampler_state(zscan->pipe, &sampler); 256 if (!zscan->samplers[i]) 257 goto error_samplers; 258 } 259 260 return true; 261 262error_samplers: 263 for (i = 0; i < 2; ++i) 264 if (zscan->samplers[i]) 265 zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]); 266 267 zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state); 268 269error_blend: 270 zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend); 271 272error_rs_state: 273 return false; 274} 275 276static void 277cleanup_state(struct vl_zscan *zscan) 278{ 279 unsigned i; 280 281 assert(zscan); 282 283 for (i = 0; i < 3; ++i) 284 zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]); 285 286 zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state); 287 zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend); 288} 289 290struct pipe_sampler_view * 291vl_zscan_linear(struct pipe_context *pipe, unsigned blocks_per_line) 292{ 293 const unsigned total_size = blocks_per_line * BLOCK_WIDTH * BLOCK_HEIGHT; 294 295 struct pipe_resource res_tmpl, *res; 296 struct pipe_sampler_view sv_tmpl, *sv; 297 struct pipe_transfer *buf_transfer; 298 unsigned x, y, i, pitch; 299 float *f; 300 301 struct pipe_box rect = 302 { 303 0, 0, 0, 304 BLOCK_WIDTH * blocks_per_line, 305 BLOCK_HEIGHT, 306 1 307 }; 308 309 assert(pipe && blocks_per_line); 310 311 memset(&res_tmpl, 0, sizeof(res_tmpl)); 312 res_tmpl.target = PIPE_TEXTURE_2D; 313 res_tmpl.format = PIPE_FORMAT_R32_FLOAT; 314 res_tmpl.width0 = BLOCK_WIDTH * blocks_per_line; 315 res_tmpl.height0 = BLOCK_HEIGHT; 316 res_tmpl.depth0 = 1; 317 res_tmpl.array_size = 1; 318 res_tmpl.usage = PIPE_USAGE_IMMUTABLE; 319 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW; 320 321 res = pipe->screen->resource_create(pipe->screen, &res_tmpl); 322 if (!res) 323 goto error_resource; 324 325 buf_transfer = pipe->get_transfer 326 ( 327 pipe, res, 328 0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, 329 &rect 330 ); 331 if (!buf_transfer) 332 goto error_transfer; 333 334 pitch = buf_transfer->stride / sizeof(float); 335 336 f = pipe->transfer_map(pipe, buf_transfer); 337 if (!f) 338 goto error_map; 339 340 for (i = 0; i < blocks_per_line; ++i) 341 for (y = 0; y < BLOCK_HEIGHT; ++y) 342 for (x = 0; x < BLOCK_WIDTH; ++x) { 343 float addr = x + y * BLOCK_WIDTH + 344 i * BLOCK_WIDTH * BLOCK_HEIGHT; 345 346 addr /= total_size; 347 348 f[i * BLOCK_WIDTH + y * pitch + x] = addr; 349 } 350 351 pipe->transfer_unmap(pipe, buf_transfer); 352 pipe->transfer_destroy(pipe, buf_transfer); 353 354 memset(&sv_tmpl, 0, sizeof(sv_tmpl)); 355 u_sampler_view_default_template(&sv_tmpl, res, res->format); 356 sv = pipe->create_sampler_view(pipe, res, &sv_tmpl); 357 pipe_resource_reference(&res, NULL); 358 if (!sv) 359 goto error_map; 360 361 return sv; 362 363error_map: 364 pipe->transfer_destroy(pipe, buf_transfer); 365 366error_transfer: 367 pipe_resource_reference(&res, NULL); 368 369error_resource: 370 return NULL; 371} 372 373#if 0 374// TODO 375struct pipe_sampler_view * 376vl_zscan_normal(struct pipe_context *pipe, unsigned blocks_per_line); 377 378struct pipe_sampler_view * 379vl_zscan_alternate(struct pipe_context *pipe, unsigned blocks_per_line); 380#endif 381 382bool 383vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe, 384 unsigned buffer_width, unsigned buffer_height, 385 unsigned blocks_per_line, unsigned blocks_total, 386 unsigned num_channels) 387{ 388 assert(zscan && pipe); 389 390 zscan->pipe = pipe; 391 zscan->buffer_width = buffer_width; 392 zscan->buffer_height = buffer_height; 393 zscan->num_channels = num_channels; 394 zscan->blocks_per_line = blocks_per_line; 395 zscan->blocks_total = blocks_total; 396 397 if(!init_shaders(zscan)) 398 return false; 399 400 if(!init_state(zscan)) { 401 cleanup_shaders(zscan); 402 return false; 403 } 404 405 return true; 406} 407 408void 409vl_zscan_cleanup(struct vl_zscan *zscan) 410{ 411 assert(zscan); 412 413 cleanup_shaders(zscan); 414 cleanup_state(zscan); 415} 416 417void 418vl_zscan_set_layout(struct vl_zscan *zscan, struct pipe_sampler_view *layout) 419{ 420 assert(zscan); 421 assert(layout); 422 423 pipe_sampler_view_reference(&zscan->scan, layout); 424} 425 426#if 0 427// TODO 428void 429vl_zscan_upload_quant(struct vl_zscan *zscan, ...); 430#endif 431 432bool 433vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, 434 struct pipe_sampler_view *src, struct pipe_surface *dst) 435{ 436 assert(zscan && buffer); 437 438 memset(buffer, 0, sizeof(struct vl_zscan_buffer)); 439 440 buffer->zscan = zscan; 441 442 pipe_sampler_view_reference(&buffer->src, src); 443 pipe_sampler_view_reference(&buffer->scan, zscan->scan); 444 pipe_sampler_view_reference(&buffer->quant, zscan->quant); 445 446 buffer->viewport.scale[0] = dst->width; 447 buffer->viewport.scale[1] = dst->height; 448 buffer->viewport.scale[2] = 1; 449 buffer->viewport.scale[3] = 1; 450 buffer->viewport.translate[0] = 0; 451 buffer->viewport.translate[1] = 0; 452 buffer->viewport.translate[2] = 0; 453 buffer->viewport.translate[3] = 0; 454 455 buffer->fb_state.width = dst->width; 456 buffer->fb_state.height = dst->height; 457 buffer->fb_state.nr_cbufs = 1; 458 pipe_surface_reference(&buffer->fb_state.cbufs[0], dst); 459 460 return true; 461} 462 463void 464vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer) 465{ 466 assert(buffer); 467 468 pipe_sampler_view_reference(&buffer->src, NULL); 469 pipe_sampler_view_reference(&buffer->scan, NULL); 470 pipe_sampler_view_reference(&buffer->quant, NULL); 471 pipe_surface_reference(&buffer->fb_state.cbufs[0], NULL); 472} 473 474void 475vl_zscan_render(struct vl_zscan_buffer *buffer, unsigned num_instances) 476{ 477 struct vl_zscan *zscan; 478 479 assert(buffer); 480 481 zscan = buffer->zscan; 482 483 zscan->pipe->bind_rasterizer_state(zscan->pipe, zscan->rs_state); 484 zscan->pipe->bind_blend_state(zscan->pipe, zscan->blend); 485 zscan->pipe->bind_fragment_sampler_states(zscan->pipe, 2, zscan->samplers); 486 zscan->pipe->set_framebuffer_state(zscan->pipe, &buffer->fb_state); 487 zscan->pipe->set_viewport_state(zscan->pipe, &buffer->viewport); 488 zscan->pipe->set_fragment_sampler_views(zscan->pipe, 2, &buffer->src); 489 zscan->pipe->bind_vs_state(zscan->pipe, zscan->vs); 490 zscan->pipe->bind_fs_state(zscan->pipe, zscan->fs); 491 util_draw_arrays_instanced(zscan->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances); 492} 493