vg_context.c revision b730f0fc52a208b5f2a308199724ab02aa391fec
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/************************************************************************** 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright 2009 VMware, Inc. All Rights Reserved. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * copy of this software and associated documentation files (the 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * "Software"), to deal in the Software without restriction, including 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish, 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the following conditions: 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The above copyright notice and this permission notice (including the 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * of the Software. 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) **************************************************************************/ 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "vg_context.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "paint.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "renderer.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "shaders_cache.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "shader.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "asm_util.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "st_inlines.h" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "vg_manager.h" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "api.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 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 48struct vg_context *_vg_context = 0; 49 50struct vg_context * vg_current_context(void) 51{ 52 return _vg_context; 53} 54 55static void init_clear(struct vg_context *st) 56{ 57 struct pipe_context *pipe = st->pipe; 58 59 /* rasterizer state: bypass clipping */ 60 memset(&st->clear.raster, 0, sizeof(st->clear.raster)); 61 st->clear.raster.gl_rasterization_rules = 1; 62 63 /* fragment shader state: color pass-through program */ 64 st->clear.fs = 65 util_make_fragment_passthrough_shader(pipe); 66} 67 68/** 69 * A depth/stencil rb will be needed regardless of what the visual says. 70 */ 71static boolean 72choose_depth_stencil_format(struct vg_context *ctx) 73{ 74 struct pipe_screen *screen = ctx->pipe->screen; 75 enum pipe_format formats[] = { 76 PIPE_FORMAT_Z24_UNORM_S8_USCALED, 77 PIPE_FORMAT_S8_USCALED_Z24_UNORM, 78 PIPE_FORMAT_NONE 79 }; 80 enum pipe_format *fmt; 81 82 for (fmt = formats; *fmt != PIPE_FORMAT_NONE; fmt++) { 83 if (screen->is_format_supported(screen, *fmt, 84 PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0)) 85 break; 86 } 87 88 ctx->ds_format = *fmt; 89 90 return (ctx->ds_format != PIPE_FORMAT_NONE); 91} 92 93void vg_set_current_context(struct vg_context *ctx) 94{ 95 _vg_context = ctx; 96 api_make_dispatch_current((ctx) ? ctx->dispatch : NULL); 97} 98 99struct vg_context * vg_create_context(struct pipe_context *pipe, 100 const void *visual, 101 struct vg_context *share) 102{ 103 struct vg_context *ctx; 104 unsigned i; 105 106 ctx = CALLOC_STRUCT(vg_context); 107 108 ctx->pipe = pipe; 109 if (!choose_depth_stencil_format(ctx)) { 110 FREE(ctx); 111 return NULL; 112 } 113 114 ctx->dispatch = api_create_dispatch(); 115 116 vg_init_state(&ctx->state.vg); 117 ctx->state.dirty = ALL_DIRTY; 118 119 ctx->cso_context = cso_create_context(pipe); 120 121 init_clear(ctx); 122 123 ctx->default_paint = paint_create(ctx); 124 ctx->state.vg.stroke_paint = ctx->default_paint; 125 ctx->state.vg.fill_paint = ctx->default_paint; 126 127 128 ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 129 ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 130 ctx->mask.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 131 ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 132 ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 133 ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 134 ctx->mask.sampler.normalized_coords = 0; 135 136 ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 137 ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 138 ctx->blend_sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 139 ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 140 ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 141 ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 142 ctx->blend_sampler.normalized_coords = 0; 143 144 for (i = 0; i < 2; i++) { 145 ctx->velems[i].src_offset = i * 4 * sizeof(float); 146 ctx->velems[i].instance_divisor = 0; 147 ctx->velems[i].vertex_buffer_index = 0; 148 ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 149 } 150 151 vg_set_error(ctx, VG_NO_ERROR); 152 153 ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create(); 154 ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create(); 155 ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create(); 156 ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create(); 157 ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create(); 158 159 ctx->renderer = renderer_create(ctx); 160 ctx->sc = shaders_cache_create(ctx); 161 ctx->shader = shader_create(ctx); 162 163 ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context); 164 165 return ctx; 166} 167 168void vg_destroy_context(struct vg_context *ctx) 169{ 170 struct pipe_resource **cbuf = &ctx->mask.cbuf; 171 struct pipe_resource **vsbuf = &ctx->vs_const_buffer; 172 173 util_destroy_blit(ctx->blit); 174 renderer_destroy(ctx->renderer); 175 shaders_cache_destroy(ctx->sc); 176 shader_destroy(ctx->shader); 177 paint_destroy(ctx->default_paint); 178 179 if (*cbuf) 180 pipe_resource_reference(cbuf, NULL); 181 182 if (*vsbuf) 183 pipe_resource_reference(vsbuf, NULL); 184 185 if (ctx->clear.fs) { 186 cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs); 187 ctx->clear.fs = NULL; 188 } 189 190 if (ctx->plain_vs) { 191 vg_shader_destroy(ctx, ctx->plain_vs); 192 ctx->plain_vs = NULL; 193 } 194 if (ctx->clear_vs) { 195 vg_shader_destroy(ctx, ctx->clear_vs); 196 ctx->clear_vs = NULL; 197 } 198 if (ctx->texture_vs) { 199 vg_shader_destroy(ctx, ctx->texture_vs); 200 ctx->texture_vs = NULL; 201 } 202 203 if (ctx->pass_through_depth_fs) 204 vg_shader_destroy(ctx, ctx->pass_through_depth_fs); 205 if (ctx->mask.union_fs) 206 vg_shader_destroy(ctx, ctx->mask.union_fs); 207 if (ctx->mask.intersect_fs) 208 vg_shader_destroy(ctx, ctx->mask.intersect_fs); 209 if (ctx->mask.subtract_fs) 210 vg_shader_destroy(ctx, ctx->mask.subtract_fs); 211 if (ctx->mask.set_fs) 212 vg_shader_destroy(ctx, ctx->mask.set_fs); 213 214 cso_release_all(ctx->cso_context); 215 cso_destroy_context(ctx->cso_context); 216 217 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]); 218 cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]); 219 cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]); 220 cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]); 221 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]); 222 223 api_destroy_dispatch(ctx->dispatch); 224 225 FREE(ctx); 226} 227 228void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type) 229{ 230 obj->type = type; 231 obj->ctx = ctx; 232} 233 234VGboolean vg_context_is_object_valid(struct vg_context *ctx, 235 enum vg_object_type type, 236 void *ptr) 237{ 238 if (ctx) { 239 struct cso_hash *hash = ctx->owned_objects[type]; 240 if (!hash) 241 return VG_FALSE; 242 return cso_hash_contains(hash, (unsigned)(long)ptr); 243 } 244 return VG_FALSE; 245} 246 247void vg_context_add_object(struct vg_context *ctx, 248 enum vg_object_type type, 249 void *ptr) 250{ 251 if (ctx) { 252 struct cso_hash *hash = ctx->owned_objects[type]; 253 if (!hash) 254 return; 255 cso_hash_insert(hash, (unsigned)(long)ptr, ptr); 256 } 257} 258 259void vg_context_remove_object(struct vg_context *ctx, 260 enum vg_object_type type, 261 void *ptr) 262{ 263 if (ctx) { 264 struct cso_hash *hash = ctx->owned_objects[type]; 265 if (!hash) 266 return; 267 cso_hash_take(hash, (unsigned)(long)ptr); 268 } 269} 270 271void vg_validate_state(struct vg_context *ctx) 272{ 273 vg_manager_validate_framebuffer(ctx); 274 275 renderer_validate(ctx->renderer, ctx->state.dirty, 276 ctx->draw_buffer, &ctx->state.vg); 277 278 ctx->state.dirty = NONE_DIRTY; 279 280 shader_set_masking(ctx->shader, ctx->state.vg.masking); 281 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); 282} 283 284VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type) 285{ 286 struct vg_object *obj = ptr; 287 if (ptr && is_aligned(obj) && obj->type == type) 288 return VG_TRUE; 289 else 290 return VG_FALSE; 291} 292 293void vg_set_error(struct vg_context *ctx, 294 VGErrorCode code) 295{ 296 /*vgGetError returns the oldest error code provided by 297 * an API call on the current context since the previous 298 * call to vgGetError on that context (or since the creation 299 of the context).*/ 300 if (ctx->_error == VG_NO_ERROR) 301 ctx->_error = code; 302} 303 304void vg_prepare_blend_surface(struct vg_context *ctx) 305{ 306 struct pipe_surface *dest_surface = NULL; 307 struct pipe_context *pipe = ctx->pipe; 308 struct pipe_sampler_view *view; 309 struct pipe_sampler_view view_templ; 310 struct st_framebuffer *stfb = ctx->draw_buffer; 311 struct st_renderbuffer *strb = stfb->strb; 312 313 /* first finish all pending rendering */ 314 vgFinish(); 315 316 u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format); 317 view = pipe->create_sampler_view(pipe, strb->texture, &view_templ); 318 319 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 320 stfb->blend_texture_view->texture, 321 0, 0, 0, 322 PIPE_BIND_RENDER_TARGET); 323 util_blit_pixels_tex(ctx->blit, 324 view, 325 0, 0, 326 strb->width, strb->height, 327 dest_surface, 328 0, 0, 329 strb->width, strb->height, 330 0.0, PIPE_TEX_MIPFILTER_NEAREST); 331 332 if (dest_surface) 333 pipe_surface_reference(&dest_surface, NULL); 334 335 /* make sure it's complete */ 336 vgFinish(); 337 338 pipe_sampler_view_reference(&view, NULL); 339} 340 341 342void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) 343{ 344 struct pipe_surface *dest_surface = NULL; 345 struct pipe_context *pipe = ctx->pipe; 346 struct st_framebuffer *stfb = ctx->draw_buffer; 347 struct st_renderbuffer *strb = stfb->strb; 348 349 vg_validate_state(ctx); 350 351 /* first finish all pending rendering */ 352 vgFinish(); 353 354 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 355 stfb->blend_texture_view->texture, 356 0, 0, 0, 357 PIPE_BIND_RENDER_TARGET); 358 359 /* flip it, because we want to use it as a sampler */ 360 util_blit_pixels_tex(ctx->blit, 361 stfb->alpha_mask_view, 362 0, strb->height, 363 strb->width, 0, 364 dest_surface, 365 0, 0, 366 strb->width, strb->height, 367 0.0, PIPE_TEX_MIPFILTER_NEAREST); 368 369 /* make sure it's complete */ 370 vgFinish(); 371 372 if (dest_surface) 373 pipe_surface_reference(&dest_surface, NULL); 374} 375 376void * vg_plain_vs(struct vg_context *ctx) 377{ 378 if (!ctx->plain_vs) { 379 ctx->plain_vs = shader_create_from_text(ctx->pipe, 380 vs_plain_asm, 381 200, 382 PIPE_SHADER_VERTEX); 383 } 384 385 return ctx->plain_vs->driver; 386} 387 388 389void * vg_clear_vs(struct vg_context *ctx) 390{ 391 if (!ctx->clear_vs) { 392 ctx->clear_vs = shader_create_from_text(ctx->pipe, 393 vs_clear_asm, 394 200, 395 PIPE_SHADER_VERTEX); 396 } 397 398 return ctx->clear_vs->driver; 399} 400 401void * vg_texture_vs(struct vg_context *ctx) 402{ 403 if (!ctx->texture_vs) { 404 ctx->texture_vs = shader_create_from_text(ctx->pipe, 405 vs_texture_asm, 406 200, 407 PIPE_SHADER_VERTEX); 408 } 409 410 return ctx->texture_vs->driver; 411} 412