svga: create BGRX render target view for BGRX_UNORM surface
[mesa.git] / src / gallium / drivers / svga / svga_surface.c
1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26 #include "svga_cmd.h"
27
28 #include "pipe/p_state.h"
29 #include "pipe/p_defines.h"
30 #include "util/u_inlines.h"
31 #include "os/os_thread.h"
32 #include "util/u_bitmask.h"
33 #include "util/u_format.h"
34 #include "util/u_math.h"
35 #include "util/u_memory.h"
36
37 #include "svga_format.h"
38 #include "svga_screen.h"
39 #include "svga_context.h"
40 #include "svga_sampler_view.h"
41 #include "svga_resource_texture.h"
42 #include "svga_surface.h"
43 #include "svga_debug.h"
44
45 static void svga_mark_surface_dirty(struct pipe_surface *surf);
46
47 void
48 svga_texture_copy_handle(struct svga_context *svga,
49 struct svga_winsys_surface *src_handle,
50 unsigned src_x, unsigned src_y, unsigned src_z,
51 unsigned src_level, unsigned src_layer,
52 struct svga_winsys_surface *dst_handle,
53 unsigned dst_x, unsigned dst_y, unsigned dst_z,
54 unsigned dst_level, unsigned dst_layer,
55 unsigned width, unsigned height, unsigned depth)
56 {
57 struct svga_surface dst, src;
58 enum pipe_error ret;
59 SVGA3dCopyBox box, *boxes;
60
61 assert(svga);
62
63 src.handle = src_handle;
64 src.real_level = src_level;
65 src.real_layer = src_layer;
66 src.real_zslice = 0;
67
68 dst.handle = dst_handle;
69 dst.real_level = dst_level;
70 dst.real_layer = dst_layer;
71 dst.real_zslice = 0;
72
73 box.x = dst_x;
74 box.y = dst_y;
75 box.z = dst_z;
76 box.w = width;
77 box.h = height;
78 box.d = depth;
79 box.srcx = src_x;
80 box.srcy = src_y;
81 box.srcz = src_z;
82
83 /*
84 SVGA_DBG(DEBUG_VIEWS, "mipcopy src: %p %u (%ux%ux%u), dst: %p %u (%ux%ux%u)\n",
85 src_handle, src_level, src_x, src_y, src_z,
86 dst_handle, dst_level, dst_x, dst_y, dst_z);
87 */
88
89 ret = SVGA3D_BeginSurfaceCopy(svga->swc,
90 &src.base,
91 &dst.base,
92 &boxes, 1);
93 if (ret != PIPE_OK) {
94 svga_context_flush(svga, NULL);
95 ret = SVGA3D_BeginSurfaceCopy(svga->swc,
96 &src.base,
97 &dst.base,
98 &boxes, 1);
99 assert(ret == PIPE_OK);
100 }
101 *boxes = box;
102 SVGA_FIFOCommitAll(svga->swc);
103 }
104
105
106 struct svga_winsys_surface *
107 svga_texture_view_surface(struct svga_context *svga,
108 struct svga_texture *tex,
109 unsigned bind_flags,
110 SVGA3dSurfaceFlags flags,
111 SVGA3dSurfaceFormat format,
112 unsigned start_mip,
113 unsigned num_mip,
114 int layer_pick,
115 unsigned num_layers,
116 int zslice_pick,
117 struct svga_host_surface_cache_key *key) /* OUT */
118 {
119 struct svga_screen *ss = svga_screen(svga->pipe.screen);
120 struct svga_winsys_surface *handle;
121 uint32_t i, j;
122 unsigned z_offset = 0;
123
124 SVGA_DBG(DEBUG_PERF,
125 "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
126 layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
127
128 key->flags = flags;
129 key->format = format;
130 key->numMipLevels = num_mip;
131 key->size.width = u_minify(tex->b.b.width0, start_mip);
132 key->size.height = u_minify(tex->b.b.height0, start_mip);
133 key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
134 key->cachable = 1;
135 key->arraySize = 1;
136 key->numFaces = 1;
137
138 /* single sample surface can be treated as non-multisamples surface */
139 key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
140
141 if (key->sampleCount > 1) {
142 key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
143 }
144
145 if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
146 key->flags |= SVGA3D_SURFACE_CUBEMAP;
147 key->numFaces = 6;
148 } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
149 tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
150 key->arraySize = num_layers;
151 }
152
153 if (key->format == SVGA3D_FORMAT_INVALID) {
154 key->cachable = 0;
155 return NULL;
156 }
157
158 SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
159 handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, key);
160 if (!handle) {
161 key->cachable = 0;
162 return NULL;
163 }
164
165 SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
166
167 if (layer_pick < 0)
168 layer_pick = 0;
169
170 if (zslice_pick >= 0)
171 z_offset = zslice_pick;
172
173 for (i = 0; i < key->numMipLevels; i++) {
174 for (j = 0; j < key->numFaces * key->arraySize; j++) {
175 if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) {
176 unsigned depth = (zslice_pick < 0 ?
177 u_minify(tex->b.b.depth0, i + start_mip) :
178 1);
179
180 svga_texture_copy_handle(svga,
181 tex->handle,
182 0, 0, z_offset,
183 i + start_mip,
184 j + layer_pick,
185 handle, 0, 0, 0, i, j,
186 u_minify(tex->b.b.width0, i + start_mip),
187 u_minify(tex->b.b.height0, i + start_mip),
188 depth);
189 }
190 }
191 }
192
193 return handle;
194 }
195
196
197 /**
198 * A helper function to create a surface view.
199 * The view boolean flag specifies whether svga_texture_view_surface()
200 * will be called to create a cloned surface and resource for the view.
201 */
202 static struct pipe_surface *
203 svga_create_surface_view(struct pipe_context *pipe,
204 struct pipe_resource *pt,
205 const struct pipe_surface *surf_tmpl,
206 boolean view)
207 {
208 struct svga_context *svga = svga_context(pipe);
209 struct svga_texture *tex = svga_texture(pt);
210 struct pipe_screen *screen = pipe->screen;
211 struct svga_screen *ss = svga_screen(screen);
212 struct svga_surface *s;
213 unsigned layer, zslice, bind;
214 unsigned nlayers = 1;
215 SVGA3dSurfaceFlags flags = 0;
216 SVGA3dSurfaceFormat format;
217 struct pipe_surface *retVal = NULL;
218
219 s = CALLOC_STRUCT(svga_surface);
220 if (!s)
221 return NULL;
222
223 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
224
225 if (pt->target == PIPE_TEXTURE_CUBE) {
226 layer = surf_tmpl->u.tex.first_layer;
227 zslice = 0;
228 }
229 else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
230 pt->target == PIPE_TEXTURE_2D_ARRAY) {
231 layer = surf_tmpl->u.tex.first_layer;
232 zslice = 0;
233 nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
234 }
235 else {
236 layer = 0;
237 zslice = surf_tmpl->u.tex.first_layer;
238 }
239
240 pipe_reference_init(&s->base.reference, 1);
241 pipe_resource_reference(&s->base.texture, pt);
242 s->base.context = pipe;
243 s->base.format = surf_tmpl->format;
244 s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
245 s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
246 s->base.u.tex.level = surf_tmpl->u.tex.level;
247 s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
248 s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
249 s->view_id = SVGA3D_INVALID_ID;
250
251 s->backed = NULL;
252
253 if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
254 flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
255 SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
256 bind = PIPE_BIND_DEPTH_STENCIL;
257 }
258 else {
259 flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
260 SVGA3D_SURFACE_BIND_RENDER_TARGET;
261 bind = PIPE_BIND_RENDER_TARGET;
262 }
263
264 if (tex->imported)
265 format = tex->key.format;
266 else
267 format = svga_translate_format(ss, surf_tmpl->format, bind);
268
269 assert(format != SVGA3D_FORMAT_INVALID);
270
271 if (view) {
272 SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n",
273 pt, surf_tmpl->u.tex.level, layer, zslice, s);
274
275 if (svga_have_vgpu10(svga)) {
276 switch (pt->target) {
277 case PIPE_TEXTURE_1D:
278 flags |= SVGA3D_SURFACE_1D;
279 break;
280 case PIPE_TEXTURE_1D_ARRAY:
281 flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
282 break;
283 case PIPE_TEXTURE_2D_ARRAY:
284 flags |= SVGA3D_SURFACE_ARRAY;
285 break;
286 case PIPE_TEXTURE_3D:
287 flags |= SVGA3D_SURFACE_VOLUME;
288 break;
289 case PIPE_TEXTURE_CUBE:
290 if (nlayers == 6)
291 flags |= SVGA3D_SURFACE_CUBEMAP;
292 break;
293 default:
294 break;
295 }
296 }
297
298 /* When we clone the surface view resource, use the format used in
299 * the creation of the original resource.
300 */
301 s->handle = svga_texture_view_surface(svga, tex, bind, flags,
302 tex->key.format,
303 surf_tmpl->u.tex.level, 1,
304 layer, nlayers, zslice, &s->key);
305 if (!s->handle) {
306 FREE(s);
307 goto done;
308 }
309
310 s->key.format = format;
311 s->real_layer = 0;
312 s->real_level = 0;
313 s->real_zslice = 0;
314 } else {
315 SVGA_DBG(DEBUG_VIEWS,
316 "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n",
317 pt, surf_tmpl->u.tex.level, layer, zslice, s);
318
319 memset(&s->key, 0, sizeof s->key);
320 s->key.format = format;
321 s->handle = tex->handle;
322 s->real_layer = layer;
323 s->real_zslice = zslice;
324 s->real_level = surf_tmpl->u.tex.level;
325 }
326
327 svga->hud.num_surface_views++;
328 retVal = &s->base;
329
330 done:
331 SVGA_STATS_TIME_POP(ss->sws);
332 return retVal;
333 }
334
335
336 static struct pipe_surface *
337 svga_create_surface(struct pipe_context *pipe,
338 struct pipe_resource *pt,
339 const struct pipe_surface *surf_tmpl)
340 {
341 struct svga_context *svga = svga_context(pipe);
342 struct pipe_screen *screen = pipe->screen;
343 struct pipe_surface *surf = NULL;
344 boolean view = FALSE;
345
346 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
347
348 if (svga_screen(screen)->debug.force_surface_view)
349 view = TRUE;
350
351 if (surf_tmpl->u.tex.level != 0 &&
352 svga_screen(screen)->debug.force_level_surface_view)
353 view = TRUE;
354
355 if (pt->target == PIPE_TEXTURE_3D)
356 view = TRUE;
357
358 if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
359 view = FALSE;
360
361 surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
362
363 SVGA_STATS_TIME_POP(svga_sws(svga));
364
365 return surf;
366 }
367
368
369 /**
370 * Clone the surface view and its associated resource.
371 */
372 static struct svga_surface *
373 create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
374 {
375 SVGA_STATS_TIME_PUSH(svga_sws(svga),
376 SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
377
378 if (!s->backed) {
379 struct svga_texture *tex = svga_texture(s->base.texture);
380 struct pipe_surface *backed_view;
381
382 backed_view = svga_create_surface_view(&svga->pipe,
383 &tex->b.b,
384 &s->base,
385 TRUE);
386 if (!backed_view)
387 return NULL;
388
389 s->backed = svga_surface(backed_view);
390 }
391
392 svga_mark_surface_dirty(&s->backed->base);
393
394 SVGA_STATS_TIME_POP(svga_sws(svga));
395
396 return s->backed;
397 }
398
399 /**
400 * Create a DX RenderTarget/DepthStencil View for the given surface,
401 * if needed.
402 */
403 struct pipe_surface *
404 svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
405 {
406 enum pipe_error ret = PIPE_OK;
407 enum pipe_shader_type shader;
408
409 assert(svga_have_vgpu10(svga));
410 assert(s);
411
412 SVGA_STATS_TIME_PUSH(svga_sws(svga),
413 SVGA_STATS_TIME_VALIDATESURFACEVIEW);
414
415 /**
416 * DX spec explicitly specifies that no resource can be bound to a render
417 * target view and a shader resource view simultanously.
418 * So first check if the resource bound to this surface view collides with
419 * a sampler view. If so, then we will clone this surface view and its
420 * associated resource. We will then use the cloned surface view for
421 * render target.
422 */
423 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
424 if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
425 SVGA_DBG(DEBUG_VIEWS,
426 "same resource used in shaderResource and renderTarget 0x%x\n",
427 s->handle);
428 s = create_backed_surface_view(svga, s);
429 /* s may be null here if the function failed */
430 break;
431 }
432 }
433
434 if (s && s->view_id == SVGA3D_INVALID_ID) {
435 SVGA3dResourceType resType;
436 SVGA3dRenderTargetViewDesc desc;
437
438 desc.tex.mipSlice = s->real_level;
439 desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
440 desc.tex.arraySize =
441 s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
442
443 s->view_id = util_bitmask_add(svga->surface_view_id_bm);
444
445 resType = svga_resource_type(s->base.texture->target);
446
447 if (util_format_is_depth_or_stencil(s->base.format)) {
448 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
449 s->view_id,
450 s->handle,
451 s->key.format,
452 resType,
453 &desc);
454 }
455 else {
456 SVGA3dSurfaceFormat view_format = s->key.format;
457 const struct svga_texture *stex = svga_texture(s->base.texture);
458
459 /* Can't create RGBA render target view of a RGBX surface so adjust
460 * the view format. We do something similar for texture samplers in
461 * svga_validate_pipe_sampler_view().
462 */
463 if (view_format == SVGA3D_B8G8R8A8_UNORM &&
464 (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
465 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
466 view_format = SVGA3D_B8G8R8X8_UNORM;
467 }
468
469 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
470 s->view_id,
471 s->handle,
472 view_format,
473 resType,
474 &desc);
475 }
476
477 if (ret != PIPE_OK) {
478 util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
479 s->view_id = SVGA3D_INVALID_ID;
480 s = NULL;
481 }
482 }
483
484 SVGA_STATS_TIME_POP(svga_sws(svga));
485
486 return s ? &s->base : NULL;
487 }
488
489
490
491 static void
492 svga_surface_destroy(struct pipe_context *pipe,
493 struct pipe_surface *surf)
494 {
495 struct svga_context *svga = svga_context(pipe);
496 struct svga_surface *s = svga_surface(surf);
497 struct svga_texture *t = svga_texture(surf->texture);
498 struct svga_screen *ss = svga_screen(surf->texture->screen);
499 enum pipe_error ret = PIPE_OK;
500
501 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
502
503 /* Destroy the backed view surface if it exists */
504 if (s->backed) {
505 svga_surface_destroy(pipe, &s->backed->base);
506 s->backed = NULL;
507 }
508
509 if (s->handle != t->handle) {
510 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
511 svga_screen_surface_destroy(ss, &s->key, &s->handle);
512 }
513
514 if (s->view_id != SVGA3D_INVALID_ID) {
515 unsigned try;
516
517 assert(svga_have_vgpu10(svga));
518 for (try = 0; try < 2; try++) {
519 if (util_format_is_depth_or_stencil(s->base.format)) {
520 ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
521 }
522 else {
523 ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
524 }
525 if (ret == PIPE_OK)
526 break;
527 svga_context_flush(svga, NULL);
528 }
529 assert(ret == PIPE_OK);
530 util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
531 }
532
533 pipe_resource_reference(&surf->texture, NULL);
534 FREE(surf);
535
536 svga->hud.num_surface_views--;
537 SVGA_STATS_TIME_POP(ss->sws);
538 }
539
540
541 static void
542 svga_mark_surface_dirty(struct pipe_surface *surf)
543 {
544 struct svga_surface *s = svga_surface(surf);
545 struct svga_texture *tex = svga_texture(surf->texture);
546
547 if (!s->dirty) {
548 s->dirty = TRUE;
549
550 if (s->handle == tex->handle) {
551 /* hmm so 3d textures always have all their slices marked ? */
552 svga_define_texture_level(tex, surf->u.tex.first_layer,
553 surf->u.tex.level);
554 }
555 else {
556 /* this will happen later in svga_propagate_surface */
557 }
558 }
559
560 /* Increment the view_age and texture age for this surface's mipmap
561 * level so that any sampler views into the texture are re-validated too.
562 */
563 svga_age_texture_view(tex, surf->u.tex.level);
564 }
565
566
567 void
568 svga_mark_surfaces_dirty(struct svga_context *svga)
569 {
570 unsigned i;
571
572 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
573 if (svga->curr.framebuffer.cbufs[i])
574 svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
575 }
576 if (svga->curr.framebuffer.zsbuf)
577 svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
578 }
579
580
581 /**
582 * Progagate any changes from surfaces to texture.
583 * pipe is optional context to inline the blit command in.
584 */
585 void
586 svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
587 {
588 struct svga_surface *s = svga_surface(surf);
589 struct svga_texture *tex = svga_texture(surf->texture);
590 struct svga_screen *ss = svga_screen(surf->texture->screen);
591
592 if (!s->dirty)
593 return;
594
595 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
596
597 s->dirty = FALSE;
598 ss->texture_timestamp++;
599 svga_age_texture_view(tex, surf->u.tex.level);
600
601 if (s->handle != tex->handle) {
602 unsigned zslice, layer;
603 unsigned nlayers = 1;
604 unsigned i;
605
606 if (surf->texture->target == PIPE_TEXTURE_CUBE) {
607 zslice = 0;
608 layer = surf->u.tex.first_layer;
609 }
610 else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
611 surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
612 zslice = 0;
613 layer = surf->u.tex.first_layer;
614 nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
615 }
616 else {
617 zslice = surf->u.tex.first_layer;
618 layer = 0;
619 }
620
621 SVGA_DBG(DEBUG_VIEWS,
622 "svga: Surface propagate: tex %p, level %u, from %p\n",
623 tex, surf->u.tex.level, surf);
624 for (i = 0; i < nlayers; i++) {
625 svga_texture_copy_handle(svga,
626 s->handle, 0, 0, 0, s->real_level,
627 s->real_layer + i,
628 tex->handle, 0, 0, zslice, surf->u.tex.level,
629 layer + i,
630 u_minify(tex->b.b.width0, surf->u.tex.level),
631 u_minify(tex->b.b.height0, surf->u.tex.level),
632 1);
633 svga_define_texture_level(tex, layer + i, surf->u.tex.level);
634 }
635 }
636
637 SVGA_STATS_TIME_POP(ss->sws);
638 }
639
640
641 /**
642 * If any of the render targets are in backing texture views, propagate any
643 * changes to them back to the original texture.
644 */
645 void
646 svga_propagate_rendertargets(struct svga_context *svga)
647 {
648 unsigned i;
649
650 /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
651 * not the svga->curr.framebuffer surfaces, because it's the former
652 * surfaces which may be backing surface views (the actual render targets).
653 */
654 for (i = 0; i < svga->state.hw_draw.num_rendertargets; i++) {
655 struct pipe_surface *s = svga->state.hw_draw.rtv[i];
656 if (s) {
657 svga_propagate_surface(svga, s);
658 }
659 }
660
661 if (svga->state.hw_draw.dsv) {
662 svga_propagate_surface(svga, svga->state.hw_draw.dsv);
663 }
664 }
665
666
667 /**
668 * Check if we should call svga_propagate_surface on the surface.
669 */
670 boolean
671 svga_surface_needs_propagation(const struct pipe_surface *surf)
672 {
673 const struct svga_surface *s = svga_surface_const(surf);
674 struct svga_texture *tex = svga_texture(surf->texture);
675
676 return s->dirty && s->handle != tex->handle;
677 }
678
679
680 static void
681 svga_get_sample_position(struct pipe_context *context,
682 unsigned sample_count, unsigned sample_index,
683 float *pos_out)
684 {
685 /* We can't actually query the device to learn the sample positions.
686 * These were grabbed from nvidia's driver.
687 */
688 static const float pos1[1][2] = {
689 { 0.5, 0.5 }
690 };
691 static const float pos4[4][2] = {
692 { 0.375000, 0.125000 },
693 { 0.875000, 0.375000 },
694 { 0.125000, 0.625000 },
695 { 0.625000, 0.875000 }
696 };
697 static const float pos8[8][2] = {
698 { 0.562500, 0.312500 },
699 { 0.437500, 0.687500 },
700 { 0.812500, 0.562500 },
701 { 0.312500, 0.187500 },
702 { 0.187500, 0.812500 },
703 { 0.062500, 0.437500 },
704 { 0.687500, 0.937500 },
705 { 0.937500, 0.062500 }
706 };
707 static const float pos16[16][2] = {
708 { 0.187500, 0.062500 },
709 { 0.437500, 0.187500 },
710 { 0.062500, 0.312500 },
711 { 0.312500, 0.437500 },
712 { 0.687500, 0.062500 },
713 { 0.937500, 0.187500 },
714 { 0.562500, 0.312500 },
715 { 0.812500, 0.437500 },
716 { 0.187500, 0.562500 },
717 { 0.437500, 0.687500 },
718 { 0.062500, 0.812500 },
719 { 0.312500, 0.937500 },
720 { 0.687500, 0.562500 },
721 { 0.937500, 0.687500 },
722 { 0.562500, 0.812500 },
723 { 0.812500, 0.937500 }
724 };
725 const float (*positions)[2];
726
727 switch (sample_count) {
728 case 4:
729 positions = pos4;
730 break;
731 case 8:
732 positions = pos8;
733 break;
734 case 16:
735 positions = pos16;
736 break;
737 default:
738 positions = pos1;
739 }
740
741 pos_out[0] = positions[sample_index][0];
742 pos_out[1] = positions[sample_index][1];
743 }
744
745
746 void
747 svga_init_surface_functions(struct svga_context *svga)
748 {
749 svga->pipe.create_surface = svga_create_surface;
750 svga->pipe.surface_destroy = svga_surface_destroy;
751 svga->pipe.get_sample_position = svga_get_sample_position;
752 }