vg_context.c revision 54cb382ea55610688c97465ef048a4990b8fd4d7
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include "vg_context.h" 28 29#include "paint.h" 30#include "renderer.h" 31#include "shaders_cache.h" 32#include "shader.h" 33#include "asm_util.h" 34#include "st_inlines.h" 35#include "vg_manager.h" 36#include "api.h" 37 38#include "pipe/p_context.h" 39#include "util/u_inlines.h" 40 41#include "cso_cache/cso_context.h" 42 43#include "util/u_simple_shaders.h" 44#include "util/u_memory.h" 45#include "util/u_blit.h" 46#include "util/u_sampler.h" 47#include "util/u_math.h" 48 49struct vg_context *_vg_context = 0; 50 51struct vg_context * vg_current_context(void) 52{ 53 return _vg_context; 54} 55 56static void init_clear(struct vg_context *st) 57{ 58 struct pipe_context *pipe = st->pipe; 59 60 /* rasterizer state: bypass clipping */ 61 memset(&st->clear.raster, 0, sizeof(st->clear.raster)); 62 st->clear.raster.gl_rasterization_rules = 1; 63 64 /* fragment shader state: color pass-through program */ 65 st->clear.fs = 66 util_make_fragment_passthrough_shader(pipe); 67} 68 69/** 70 * A depth/stencil rb will be needed regardless of what the visual says. 71 */ 72static boolean 73choose_depth_stencil_format(struct vg_context *ctx) 74{ 75 struct pipe_screen *screen = ctx->pipe->screen; 76 enum pipe_format formats[] = { 77 PIPE_FORMAT_Z24_UNORM_S8_USCALED, 78 PIPE_FORMAT_S8_USCALED_Z24_UNORM, 79 PIPE_FORMAT_NONE 80 }; 81 enum pipe_format *fmt; 82 83 for (fmt = formats; *fmt != PIPE_FORMAT_NONE; fmt++) { 84 if (screen->is_format_supported(screen, *fmt, 85 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) 86 break; 87 } 88 89 ctx->ds_format = *fmt; 90 91 return (ctx->ds_format != PIPE_FORMAT_NONE); 92} 93 94void vg_set_current_context(struct vg_context *ctx) 95{ 96 _vg_context = ctx; 97 api_make_dispatch_current((ctx) ? ctx->dispatch : NULL); 98} 99 100struct vg_context * vg_create_context(struct pipe_context *pipe, 101 const void *visual, 102 struct vg_context *share) 103{ 104 struct vg_context *ctx; 105 unsigned i; 106 107 ctx = CALLOC_STRUCT(vg_context); 108 109 ctx->pipe = pipe; 110 if (!choose_depth_stencil_format(ctx)) { 111 FREE(ctx); 112 return NULL; 113 } 114 115 ctx->dispatch = api_create_dispatch(); 116 117 vg_init_state(&ctx->state.vg); 118 ctx->state.dirty = ALL_DIRTY; 119 120 ctx->cso_context = cso_create_context(pipe); 121 122 init_clear(ctx); 123 124 ctx->default_paint = paint_create(ctx); 125 ctx->state.vg.stroke_paint = ctx->default_paint; 126 ctx->state.vg.fill_paint = ctx->default_paint; 127 128 129 ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 130 ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 131 ctx->mask.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 132 ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 133 ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 134 ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 135 ctx->mask.sampler.normalized_coords = 0; 136 137 ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 138 ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 139 ctx->blend_sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 140 ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 141 ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 142 ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 143 ctx->blend_sampler.normalized_coords = 0; 144 145 for (i = 0; i < 2; i++) { 146 ctx->velems[i].src_offset = i * 4 * sizeof(float); 147 ctx->velems[i].instance_divisor = 0; 148 ctx->velems[i].vertex_buffer_index = 0; 149 ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 150 } 151 152 vg_set_error(ctx, VG_NO_ERROR); 153 154 ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create(); 155 ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create(); 156 ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create(); 157 ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create(); 158 ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create(); 159 160 ctx->renderer = renderer_create(ctx); 161 ctx->sc = shaders_cache_create(ctx); 162 ctx->shader = shader_create(ctx); 163 164 ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context); 165 166 return ctx; 167} 168 169void vg_destroy_context(struct vg_context *ctx) 170{ 171 struct pipe_resource **cbuf = &ctx->mask.cbuf; 172 struct pipe_resource **vsbuf = &ctx->vs_const_buffer; 173 174 util_destroy_blit(ctx->blit); 175 renderer_destroy(ctx->renderer); 176 shaders_cache_destroy(ctx->sc); 177 shader_destroy(ctx->shader); 178 paint_destroy(ctx->default_paint); 179 180 if (*cbuf) 181 pipe_resource_reference(cbuf, NULL); 182 183 if (*vsbuf) 184 pipe_resource_reference(vsbuf, NULL); 185 186 if (ctx->clear.fs) { 187 cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs); 188 ctx->clear.fs = NULL; 189 } 190 191 if (ctx->plain_vs) { 192 vg_shader_destroy(ctx, ctx->plain_vs); 193 ctx->plain_vs = NULL; 194 } 195 if (ctx->clear_vs) { 196 vg_shader_destroy(ctx, ctx->clear_vs); 197 ctx->clear_vs = NULL; 198 } 199 if (ctx->texture_vs) { 200 vg_shader_destroy(ctx, ctx->texture_vs); 201 ctx->texture_vs = NULL; 202 } 203 204 if (ctx->pass_through_depth_fs) 205 vg_shader_destroy(ctx, ctx->pass_through_depth_fs); 206 if (ctx->mask.union_fs) 207 vg_shader_destroy(ctx, ctx->mask.union_fs); 208 if (ctx->mask.intersect_fs) 209 vg_shader_destroy(ctx, ctx->mask.intersect_fs); 210 if (ctx->mask.subtract_fs) 211 vg_shader_destroy(ctx, ctx->mask.subtract_fs); 212 if (ctx->mask.set_fs) 213 vg_shader_destroy(ctx, ctx->mask.set_fs); 214 215 cso_release_all(ctx->cso_context); 216 cso_destroy_context(ctx->cso_context); 217 218 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]); 219 cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]); 220 cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]); 221 cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]); 222 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]); 223 224 api_destroy_dispatch(ctx->dispatch); 225 226 FREE(ctx); 227} 228 229void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type) 230{ 231 obj->type = type; 232 obj->ctx = ctx; 233} 234 235VGboolean vg_context_is_object_valid(struct vg_context *ctx, 236 enum vg_object_type type, 237 void *ptr) 238{ 239 if (ctx) { 240 struct cso_hash *hash = ctx->owned_objects[type]; 241 if (!hash) 242 return VG_FALSE; 243 return cso_hash_contains(hash, (unsigned)(long)ptr); 244 } 245 return VG_FALSE; 246} 247 248void vg_context_add_object(struct vg_context *ctx, 249 enum vg_object_type type, 250 void *ptr) 251{ 252 if (ctx) { 253 struct cso_hash *hash = ctx->owned_objects[type]; 254 if (!hash) 255 return; 256 cso_hash_insert(hash, (unsigned)(long)ptr, ptr); 257 } 258} 259 260void vg_context_remove_object(struct vg_context *ctx, 261 enum vg_object_type type, 262 void *ptr) 263{ 264 if (ctx) { 265 struct cso_hash *hash = ctx->owned_objects[type]; 266 if (!hash) 267 return; 268 cso_hash_take(hash, (unsigned)(long)ptr); 269 } 270} 271 272static void update_clip_state(struct vg_context *ctx) 273{ 274 struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa; 275 struct vg_state *state = &ctx->state.vg; 276 277 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); 278 279 if (state->scissoring) { 280 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 281 int i; 282 283 renderer_scissor_begin(ctx->renderer, VG_FALSE); 284 285 for (i = 0; i < state->scissor_rects_num; ++i) { 286 const float x = state->scissor_rects[i * 4 + 0].f; 287 const float y = state->scissor_rects[i * 4 + 1].f; 288 const float width = state->scissor_rects[i * 4 + 2].f; 289 const float height = state->scissor_rects[i * 4 + 3].f; 290 VGint x0, y0, x1, y1, iw, ih; 291 292 x0 = (VGint) x; 293 y0 = (VGint) y; 294 if (x0 < 0) 295 x0 = 0; 296 if (y0 < 0) 297 y0 = 0; 298 299 /* note that x1 and y1 are exclusive */ 300 x1 = (VGint) ceilf(x + width); 301 y1 = (VGint) ceilf(y + height); 302 if (x1 > fb->width) 303 x1 = fb->width; 304 if (y1 > fb->height) 305 y1 = fb->height; 306 307 iw = x1 - x0; 308 ih = y1 - y0; 309 if (iw > 0 && ih> 0 ) 310 renderer_scissor(ctx->renderer, x0, y0, iw, ih); 311 } 312 313 renderer_scissor_end(ctx->renderer); 314 315 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ 316 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ 317 dsa->depth.func = PIPE_FUNC_GEQUAL; 318 } 319} 320 321void vg_validate_state(struct vg_context *ctx) 322{ 323 vg_manager_validate_framebuffer(ctx); 324 325 if ((ctx->state.dirty & BLEND_DIRTY)) { 326 struct pipe_blend_state *blend = &ctx->state.g3d.blend; 327 memset(blend, 0, sizeof(struct pipe_blend_state)); 328 blend->rt[0].blend_enable = 1; 329 blend->rt[0].colormask = PIPE_MASK_RGBA; 330 331 switch (ctx->state.vg.blend_mode) { 332 case VG_BLEND_SRC: 333 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 334 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 335 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 336 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 337 blend->rt[0].blend_enable = 0; 338 break; 339 case VG_BLEND_SRC_OVER: 340 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 341 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 342 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 343 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 344 break; 345 case VG_BLEND_DST_OVER: 346 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; 347 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; 348 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; 349 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; 350 break; 351 case VG_BLEND_SRC_IN: 352 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 353 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 354 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 355 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 356 break; 357 case VG_BLEND_DST_IN: 358 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; 359 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 360 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 361 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 362 break; 363 case VG_BLEND_MULTIPLY: 364 case VG_BLEND_SCREEN: 365 case VG_BLEND_DARKEN: 366 case VG_BLEND_LIGHTEN: 367 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 368 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 369 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 370 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 371 blend->rt[0].blend_enable = 0; 372 break; 373 case VG_BLEND_ADDITIVE: 374 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 375 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 376 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 377 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 378 break; 379 default: 380 assert(!"not implemented blend mode"); 381 } 382 cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend); 383 } 384 if ((ctx->state.dirty & RASTERIZER_DIRTY)) { 385 struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer; 386 memset(raster, 0, sizeof(struct pipe_rasterizer_state)); 387 raster->gl_rasterization_rules = 1; 388 cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer); 389 } 390 if ((ctx->state.dirty & VIEWPORT_DIRTY)) { 391 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 392 const VGint param_bytes = 8 * sizeof(VGfloat); 393 VGfloat vs_consts[8] = { 394 2.f/fb->width, 2.f/fb->height, 1, 1, 395 -1, -1, 0, 0 396 }; 397 struct pipe_resource **cbuf = &ctx->vs_const_buffer; 398 399 vg_set_viewport(ctx, VEGA_Y0_BOTTOM); 400 401 pipe_resource_reference(cbuf, NULL); 402 *cbuf = pipe_buffer_create(ctx->pipe->screen, 403 PIPE_BIND_CONSTANT_BUFFER, 404 param_bytes); 405 406 if (*cbuf) { 407 st_no_flush_pipe_buffer_write(ctx, *cbuf, 408 0, param_bytes, vs_consts); 409 } 410 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf); 411 } 412 if ((ctx->state.dirty & VS_DIRTY)) { 413 cso_set_vertex_shader_handle(ctx->cso_context, 414 vg_plain_vs(ctx)); 415 } 416 417 /* must be last because it renders to the depth buffer*/ 418 if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) { 419 update_clip_state(ctx); 420 cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa); 421 } 422 423 shader_set_masking(ctx->shader, ctx->state.vg.masking); 424 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); 425 426 ctx->state.dirty = NONE_DIRTY; 427} 428 429VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type) 430{ 431 struct vg_object *obj = ptr; 432 if (ptr && is_aligned(obj) && obj->type == type) 433 return VG_TRUE; 434 else 435 return VG_FALSE; 436} 437 438void vg_set_error(struct vg_context *ctx, 439 VGErrorCode code) 440{ 441 /*vgGetError returns the oldest error code provided by 442 * an API call on the current context since the previous 443 * call to vgGetError on that context (or since the creation 444 of the context).*/ 445 if (ctx->_error == VG_NO_ERROR) 446 ctx->_error = code; 447} 448 449void vg_prepare_blend_surface(struct vg_context *ctx) 450{ 451 struct pipe_surface *dest_surface = NULL; 452 struct pipe_context *pipe = ctx->pipe; 453 struct pipe_sampler_view *view; 454 struct pipe_sampler_view view_templ; 455 struct st_framebuffer *stfb = ctx->draw_buffer; 456 struct st_renderbuffer *strb = stfb->strb; 457 458 /* first finish all pending rendering */ 459 vgFinish(); 460 461 u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format); 462 view = pipe->create_sampler_view(pipe, strb->texture, &view_templ); 463 464 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 465 stfb->blend_texture_view->texture, 466 0, 0, 0, 467 PIPE_BIND_RENDER_TARGET); 468 util_blit_pixels_tex(ctx->blit, 469 view, 470 0, 0, 471 strb->width, strb->height, 472 dest_surface, 473 0, 0, 474 strb->width, strb->height, 475 0.0, PIPE_TEX_MIPFILTER_NEAREST); 476 477 if (dest_surface) 478 pipe_surface_reference(&dest_surface, NULL); 479 480 /* make sure it's complete */ 481 vgFinish(); 482 483 pipe_sampler_view_reference(&view, NULL); 484} 485 486 487void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) 488{ 489 struct pipe_surface *dest_surface = NULL; 490 struct pipe_context *pipe = ctx->pipe; 491 struct st_framebuffer *stfb = ctx->draw_buffer; 492 struct st_renderbuffer *strb = stfb->strb; 493 494 vg_validate_state(ctx); 495 496 /* first finish all pending rendering */ 497 vgFinish(); 498 499 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 500 stfb->blend_texture_view->texture, 501 0, 0, 0, 502 PIPE_BIND_RENDER_TARGET); 503 504 /* flip it, because we want to use it as a sampler */ 505 util_blit_pixels_tex(ctx->blit, 506 stfb->alpha_mask_view, 507 0, strb->height, 508 strb->width, 0, 509 dest_surface, 510 0, 0, 511 strb->width, strb->height, 512 0.0, PIPE_TEX_MIPFILTER_NEAREST); 513 514 /* make sure it's complete */ 515 vgFinish(); 516 517 if (dest_surface) 518 pipe_surface_reference(&dest_surface, NULL); 519} 520 521void * vg_plain_vs(struct vg_context *ctx) 522{ 523 if (!ctx->plain_vs) { 524 ctx->plain_vs = shader_create_from_text(ctx->pipe, 525 vs_plain_asm, 526 200, 527 PIPE_SHADER_VERTEX); 528 } 529 530 return ctx->plain_vs->driver; 531} 532 533 534void * vg_clear_vs(struct vg_context *ctx) 535{ 536 if (!ctx->clear_vs) { 537 ctx->clear_vs = shader_create_from_text(ctx->pipe, 538 vs_clear_asm, 539 200, 540 PIPE_SHADER_VERTEX); 541 } 542 543 return ctx->clear_vs->driver; 544} 545 546void * vg_texture_vs(struct vg_context *ctx) 547{ 548 if (!ctx->texture_vs) { 549 ctx->texture_vs = shader_create_from_text(ctx->pipe, 550 vs_texture_asm, 551 200, 552 PIPE_SHADER_VERTEX); 553 } 554 555 return ctx->texture_vs->driver; 556} 557 558void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation) 559{ 560 struct pipe_viewport_state viewport; 561 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 562 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f; 563 564 viewport.scale[0] = fb->width / 2.f; 565 viewport.scale[1] = fb->height / y_scale; 566 viewport.scale[2] = 1.0; 567 viewport.scale[3] = 1.0; 568 viewport.translate[0] = fb->width / 2.f; 569 viewport.translate[1] = fb->height / 2.f; 570 viewport.translate[2] = 0.0; 571 viewport.translate[3] = 0.0; 572 573 cso_set_viewport(ctx->cso_context, &viewport); 574} 575