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
svga_texture_copy_handle(struct svga_context * svga,struct svga_winsys_surface * src_handle,unsigned src_x,unsigned src_y,unsigned src_z,unsigned src_level,unsigned src_layer,struct svga_winsys_surface * dst_handle,unsigned dst_x,unsigned dst_y,unsigned dst_z,unsigned dst_level,unsigned dst_layer,unsigned width,unsigned height,unsigned depth)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 *
svga_texture_view_surface(struct svga_context * svga,struct svga_texture * tex,unsigned bind_flags,SVGA3dSurfaceFlags flags,SVGA3dSurfaceFormat format,unsigned start_mip,unsigned num_mip,int layer_pick,unsigned num_layers,int zslice_pick,struct svga_host_surface_cache_key * key)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 boolean validated;
124
125 SVGA_DBG(DEBUG_PERF,
126 "svga: Create surface view: layer %d zslice %d mips %d..%d\n",
127 layer_pick, zslice_pick, start_mip, start_mip+num_mip-1);
128
129 key->flags = flags;
130 key->format = format;
131 key->numMipLevels = num_mip;
132 key->size.width = u_minify(tex->b.b.width0, start_mip);
133 key->size.height = u_minify(tex->b.b.height0, start_mip);
134 key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1;
135 key->cachable = 1;
136 key->arraySize = 1;
137 key->numFaces = 1;
138
139 /* single sample surface can be treated as non-multisamples surface */
140 key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
141
142 if (key->sampleCount > 1) {
143 key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
144 }
145
146 if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
147 key->flags |= SVGA3D_SURFACE_CUBEMAP;
148 key->numFaces = 6;
149 } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY ||
150 tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) {
151 key->arraySize = num_layers;
152 }
153
154 if (key->format == SVGA3D_FORMAT_INVALID) {
155 key->cachable = 0;
156 return NULL;
157 }
158
159 SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n");
160 handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT,
161 &validated, key);
162 if (!handle) {
163 key->cachable = 0;
164 return NULL;
165 }
166
167 SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle);
168
169 if (layer_pick < 0)
170 layer_pick = 0;
171
172 if (zslice_pick >= 0)
173 z_offset = zslice_pick;
174
175 for (i = 0; i < key->numMipLevels; i++) {
176 for (j = 0; j < key->numFaces * key->arraySize; j++) {
177 if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) {
178 unsigned depth = (zslice_pick < 0 ?
179 u_minify(tex->b.b.depth0, i + start_mip) :
180 1);
181
182 svga_texture_copy_handle(svga,
183 tex->handle,
184 0, 0, z_offset,
185 i + start_mip,
186 j + layer_pick,
187 handle, 0, 0, 0, i, j,
188 u_minify(tex->b.b.width0, i + start_mip),
189 u_minify(tex->b.b.height0, i + start_mip),
190 depth);
191 }
192 }
193 }
194
195 return handle;
196 }
197
198
199 /**
200 * A helper function to create a surface view.
201 * The view boolean flag specifies whether svga_texture_view_surface()
202 * will be called to create a cloned surface and resource for the view.
203 */
204 static struct pipe_surface *
svga_create_surface_view(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl,boolean view)205 svga_create_surface_view(struct pipe_context *pipe,
206 struct pipe_resource *pt,
207 const struct pipe_surface *surf_tmpl,
208 boolean view)
209 {
210 struct svga_context *svga = svga_context(pipe);
211 struct svga_texture *tex = svga_texture(pt);
212 struct pipe_screen *screen = pipe->screen;
213 struct svga_screen *ss = svga_screen(screen);
214 struct svga_surface *s;
215 unsigned layer, zslice, bind;
216 unsigned nlayers = 1;
217 SVGA3dSurfaceFlags flags = 0;
218 SVGA3dSurfaceFormat format;
219 struct pipe_surface *retVal = NULL;
220
221 s = CALLOC_STRUCT(svga_surface);
222 if (!s)
223 return NULL;
224
225 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_CREATESURFACEVIEW);
226
227 if (pt->target == PIPE_TEXTURE_CUBE) {
228 layer = surf_tmpl->u.tex.first_layer;
229 zslice = 0;
230 }
231 else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
232 pt->target == PIPE_TEXTURE_2D_ARRAY) {
233 layer = surf_tmpl->u.tex.first_layer;
234 zslice = 0;
235 nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
236 }
237 else {
238 layer = 0;
239 zslice = surf_tmpl->u.tex.first_layer;
240 }
241
242 pipe_reference_init(&s->base.reference, 1);
243 pipe_resource_reference(&s->base.texture, pt);
244 s->base.context = pipe;
245 s->base.format = surf_tmpl->format;
246 s->base.width = u_minify(pt->width0, surf_tmpl->u.tex.level);
247 s->base.height = u_minify(pt->height0, surf_tmpl->u.tex.level);
248 s->base.u.tex.level = surf_tmpl->u.tex.level;
249 s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
250 s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer;
251 s->view_id = SVGA3D_INVALID_ID;
252
253 s->backed = NULL;
254
255 if (util_format_is_depth_or_stencil(surf_tmpl->format)) {
256 flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL |
257 SVGA3D_SURFACE_BIND_DEPTH_STENCIL;
258 bind = PIPE_BIND_DEPTH_STENCIL;
259 }
260 else {
261 flags = SVGA3D_SURFACE_HINT_RENDERTARGET |
262 SVGA3D_SURFACE_BIND_RENDER_TARGET;
263 bind = PIPE_BIND_RENDER_TARGET;
264 }
265
266 if (tex->imported)
267 format = tex->key.format;
268 else
269 format = svga_translate_format(ss, surf_tmpl->format, bind);
270
271 assert(format != SVGA3D_FORMAT_INVALID);
272
273 if (view) {
274 SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n",
275 pt, surf_tmpl->u.tex.level, layer, zslice, s);
276
277 if (svga_have_vgpu10(svga)) {
278 switch (pt->target) {
279 case PIPE_TEXTURE_1D:
280 flags |= SVGA3D_SURFACE_1D;
281 break;
282 case PIPE_TEXTURE_1D_ARRAY:
283 flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY;
284 break;
285 case PIPE_TEXTURE_2D_ARRAY:
286 flags |= SVGA3D_SURFACE_ARRAY;
287 break;
288 case PIPE_TEXTURE_3D:
289 flags |= SVGA3D_SURFACE_VOLUME;
290 break;
291 case PIPE_TEXTURE_CUBE:
292 if (nlayers == 6)
293 flags |= SVGA3D_SURFACE_CUBEMAP;
294 break;
295 default:
296 break;
297 }
298 }
299
300 /* When we clone the surface view resource, use the format used in
301 * the creation of the original resource.
302 */
303 s->handle = svga_texture_view_surface(svga, tex, bind, flags,
304 tex->key.format,
305 surf_tmpl->u.tex.level, 1,
306 layer, nlayers, zslice, &s->key);
307 if (!s->handle) {
308 FREE(s);
309 goto done;
310 }
311
312 s->key.format = format;
313 s->real_layer = 0;
314 s->real_level = 0;
315 s->real_zslice = 0;
316 } else {
317 SVGA_DBG(DEBUG_VIEWS,
318 "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n",
319 pt, surf_tmpl->u.tex.level, layer, zslice, s);
320
321 memset(&s->key, 0, sizeof s->key);
322 s->key.format = format;
323 s->handle = tex->handle;
324 s->real_layer = layer;
325 s->real_zslice = zslice;
326 s->real_level = surf_tmpl->u.tex.level;
327 }
328
329 svga->hud.num_surface_views++;
330 retVal = &s->base;
331
332 done:
333 SVGA_STATS_TIME_POP(ss->sws);
334 return retVal;
335 }
336
337
338 static struct pipe_surface *
svga_create_surface(struct pipe_context * pipe,struct pipe_resource * pt,const struct pipe_surface * surf_tmpl)339 svga_create_surface(struct pipe_context *pipe,
340 struct pipe_resource *pt,
341 const struct pipe_surface *surf_tmpl)
342 {
343 struct svga_context *svga = svga_context(pipe);
344 struct pipe_screen *screen = pipe->screen;
345 struct pipe_surface *surf = NULL;
346 boolean view = FALSE;
347
348 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATESURFACE);
349
350 if (svga_screen(screen)->debug.force_surface_view)
351 view = TRUE;
352
353 if (surf_tmpl->u.tex.level != 0 &&
354 svga_screen(screen)->debug.force_level_surface_view)
355 view = TRUE;
356
357 if (pt->target == PIPE_TEXTURE_3D)
358 view = TRUE;
359
360 if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view)
361 view = FALSE;
362
363 surf = svga_create_surface_view(pipe, pt, surf_tmpl, view);
364
365 SVGA_STATS_TIME_POP(svga_sws(svga));
366
367 return surf;
368 }
369
370
371 /**
372 * Clone the surface view and its associated resource.
373 */
374 static struct svga_surface *
create_backed_surface_view(struct svga_context * svga,struct svga_surface * s)375 create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
376 {
377 SVGA_STATS_TIME_PUSH(svga_sws(svga),
378 SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
379
380 if (!s->backed) {
381 struct svga_texture *tex = svga_texture(s->base.texture);
382 struct pipe_surface *backed_view;
383
384 backed_view = svga_create_surface_view(&svga->pipe,
385 &tex->b.b,
386 &s->base,
387 TRUE);
388 if (!backed_view)
389 return NULL;
390
391 s->backed = svga_surface(backed_view);
392 }
393
394 svga_mark_surface_dirty(&s->backed->base);
395
396 SVGA_STATS_TIME_POP(svga_sws(svga));
397
398 return s->backed;
399 }
400
401 /**
402 * Create a DX RenderTarget/DepthStencil View for the given surface,
403 * if needed.
404 */
405 struct pipe_surface *
svga_validate_surface_view(struct svga_context * svga,struct svga_surface * s)406 svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
407 {
408 enum pipe_error ret = PIPE_OK;
409 enum pipe_shader_type shader;
410
411 assert(svga_have_vgpu10(svga));
412 assert(s);
413
414 SVGA_STATS_TIME_PUSH(svga_sws(svga),
415 SVGA_STATS_TIME_VALIDATESURFACEVIEW);
416
417 /**
418 * DX spec explicitly specifies that no resource can be bound to a render
419 * target view and a shader resource view simultanously.
420 * So first check if the resource bound to this surface view collides with
421 * a sampler view. If so, then we will clone this surface view and its
422 * associated resource. We will then use the cloned surface view for
423 * render target.
424 */
425 for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
426 if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
427 SVGA_DBG(DEBUG_VIEWS,
428 "same resource used in shaderResource and renderTarget 0x%x\n",
429 s->handle);
430 s = create_backed_surface_view(svga, s);
431 /* s may be null here if the function failed */
432 break;
433 }
434 }
435
436 if (s && s->view_id == SVGA3D_INVALID_ID) {
437 SVGA3dResourceType resType;
438 SVGA3dRenderTargetViewDesc desc;
439 struct svga_texture *stex = svga_texture(s->base.texture);
440
441 if (stex->validated == FALSE) {
442 assert(stex->handle);
443
444 /* We are about to render into a surface that has not been validated.
445 * First invalidate the surface so that the device does not
446 * need to update the host-side copy with the invalid
447 * content when the associated mob is first bound to the surface.
448 */
449 ret = SVGA3D_InvalidateGBSurface(svga->swc, stex->handle);
450 if (ret != PIPE_OK) {
451 s = NULL;
452 goto done;
453 }
454 stex->validated = TRUE;
455 }
456
457 desc.tex.mipSlice = s->real_level;
458 desc.tex.firstArraySlice = s->real_layer + s->real_zslice;
459 desc.tex.arraySize =
460 s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1;
461
462 s->view_id = util_bitmask_add(svga->surface_view_id_bm);
463
464 resType = svga_resource_type(s->base.texture->target);
465
466 if (util_format_is_depth_or_stencil(s->base.format)) {
467 ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc,
468 s->view_id,
469 s->handle,
470 s->key.format,
471 resType,
472 &desc);
473 }
474 else {
475 SVGA3dSurfaceFormat view_format = s->key.format;
476 const struct svga_texture *stex = svga_texture(s->base.texture);
477
478 /* Can't create RGBA render target view of a RGBX surface so adjust
479 * the view format. We do something similar for texture samplers in
480 * svga_validate_pipe_sampler_view().
481 */
482 if (view_format == SVGA3D_B8G8R8A8_UNORM &&
483 (stex->key.format == SVGA3D_B8G8R8X8_UNORM ||
484 stex->key.format == SVGA3D_B8G8R8X8_TYPELESS)) {
485 view_format = SVGA3D_B8G8R8X8_UNORM;
486 }
487
488 ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc,
489 s->view_id,
490 s->handle,
491 view_format,
492 resType,
493 &desc);
494 }
495
496 if (ret != PIPE_OK) {
497 util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
498 s->view_id = SVGA3D_INVALID_ID;
499 s = NULL;
500 }
501 }
502
503 done:
504 SVGA_STATS_TIME_POP(svga_sws(svga));
505
506 return s ? &s->base : NULL;
507 }
508
509
510
511 static void
svga_surface_destroy(struct pipe_context * pipe,struct pipe_surface * surf)512 svga_surface_destroy(struct pipe_context *pipe,
513 struct pipe_surface *surf)
514 {
515 struct svga_context *svga = svga_context(pipe);
516 struct svga_surface *s = svga_surface(surf);
517 struct svga_texture *t = svga_texture(surf->texture);
518 struct svga_screen *ss = svga_screen(surf->texture->screen);
519 enum pipe_error ret = PIPE_OK;
520
521 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
522
523 /* Destroy the backed view surface if it exists */
524 if (s->backed) {
525 svga_surface_destroy(pipe, &s->backed->base);
526 s->backed = NULL;
527 }
528
529 if (s->handle != t->handle) {
530 SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
531 svga_screen_surface_destroy(ss, &s->key, &s->handle);
532 }
533
534 if (s->view_id != SVGA3D_INVALID_ID) {
535 unsigned try;
536
537 assert(svga_have_vgpu10(svga));
538 for (try = 0; try < 2; try++) {
539 if (util_format_is_depth_or_stencil(s->base.format)) {
540 ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
541 }
542 else {
543 ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
544 }
545 if (ret == PIPE_OK)
546 break;
547 svga_context_flush(svga, NULL);
548 }
549 assert(ret == PIPE_OK);
550 util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
551 }
552
553 pipe_resource_reference(&surf->texture, NULL);
554 FREE(surf);
555
556 svga->hud.num_surface_views--;
557 SVGA_STATS_TIME_POP(ss->sws);
558 }
559
560
561 static void
svga_mark_surface_dirty(struct pipe_surface * surf)562 svga_mark_surface_dirty(struct pipe_surface *surf)
563 {
564 struct svga_surface *s = svga_surface(surf);
565 struct svga_texture *tex = svga_texture(surf->texture);
566
567 if (!s->dirty) {
568 s->dirty = TRUE;
569
570 if (s->handle == tex->handle) {
571 /* hmm so 3d textures always have all their slices marked ? */
572 svga_define_texture_level(tex, surf->u.tex.first_layer,
573 surf->u.tex.level);
574 }
575 else {
576 /* this will happen later in svga_propagate_surface */
577 }
578 }
579
580 /* Increment the view_age and texture age for this surface's mipmap
581 * level so that any sampler views into the texture are re-validated too.
582 */
583 svga_age_texture_view(tex, surf->u.tex.level);
584 }
585
586
587 void
svga_mark_surfaces_dirty(struct svga_context * svga)588 svga_mark_surfaces_dirty(struct svga_context *svga)
589 {
590 unsigned i;
591
592 for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
593 if (svga->curr.framebuffer.cbufs[i])
594 svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
595 }
596 if (svga->curr.framebuffer.zsbuf)
597 svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
598 }
599
600
601 /**
602 * Progagate any changes from surfaces to texture.
603 * pipe is optional context to inline the blit command in.
604 */
605 void
svga_propagate_surface(struct svga_context * svga,struct pipe_surface * surf)606 svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
607 {
608 struct svga_surface *s = svga_surface(surf);
609 struct svga_texture *tex = svga_texture(surf->texture);
610 struct svga_screen *ss = svga_screen(surf->texture->screen);
611
612 if (!s->dirty)
613 return;
614
615 SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_PROPAGATESURFACE);
616
617 s->dirty = FALSE;
618 ss->texture_timestamp++;
619 svga_age_texture_view(tex, surf->u.tex.level);
620
621 if (s->handle != tex->handle) {
622 unsigned zslice, layer;
623 unsigned nlayers = 1;
624 unsigned i;
625
626 if (surf->texture->target == PIPE_TEXTURE_CUBE) {
627 zslice = 0;
628 layer = surf->u.tex.first_layer;
629 }
630 else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
631 surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
632 zslice = 0;
633 layer = surf->u.tex.first_layer;
634 nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
635 }
636 else {
637 zslice = surf->u.tex.first_layer;
638 layer = 0;
639 }
640
641 SVGA_DBG(DEBUG_VIEWS,
642 "svga: Surface propagate: tex %p, level %u, from %p\n",
643 tex, surf->u.tex.level, surf);
644 for (i = 0; i < nlayers; i++) {
645 svga_texture_copy_handle(svga,
646 s->handle, 0, 0, 0, s->real_level,
647 s->real_layer + i,
648 tex->handle, 0, 0, zslice, surf->u.tex.level,
649 layer + i,
650 u_minify(tex->b.b.width0, surf->u.tex.level),
651 u_minify(tex->b.b.height0, surf->u.tex.level),
652 1);
653 svga_define_texture_level(tex, layer + i, surf->u.tex.level);
654 }
655 }
656
657 SVGA_STATS_TIME_POP(ss->sws);
658 }
659
660
661 /**
662 * If any of the render targets are in backing texture views, propagate any
663 * changes to them back to the original texture.
664 */
665 void
svga_propagate_rendertargets(struct svga_context * svga)666 svga_propagate_rendertargets(struct svga_context *svga)
667 {
668 unsigned i;
669
670 /* Note that we examine the svga->state.hw_draw.framebuffer surfaces,
671 * not the svga->curr.framebuffer surfaces, because it's the former
672 * surfaces which may be backing surface views (the actual render targets).
673 */
674 for (i = 0; i < svga->state.hw_draw.num_rendertargets; i++) {
675 struct pipe_surface *s = svga->state.hw_draw.rtv[i];
676 if (s) {
677 svga_propagate_surface(svga, s);
678 }
679 }
680
681 if (svga->state.hw_draw.dsv) {
682 svga_propagate_surface(svga, svga->state.hw_draw.dsv);
683 }
684 }
685
686
687 /**
688 * Check if we should call svga_propagate_surface on the surface.
689 */
690 boolean
svga_surface_needs_propagation(const struct pipe_surface * surf)691 svga_surface_needs_propagation(const struct pipe_surface *surf)
692 {
693 const struct svga_surface *s = svga_surface_const(surf);
694 struct svga_texture *tex = svga_texture(surf->texture);
695
696 return s->dirty && s->handle != tex->handle;
697 }
698
699
700 static void
svga_get_sample_position(struct pipe_context * context,unsigned sample_count,unsigned sample_index,float * pos_out)701 svga_get_sample_position(struct pipe_context *context,
702 unsigned sample_count, unsigned sample_index,
703 float *pos_out)
704 {
705 /* We can't actually query the device to learn the sample positions.
706 * These were grabbed from nvidia's driver.
707 */
708 static const float pos1[1][2] = {
709 { 0.5, 0.5 }
710 };
711 static const float pos4[4][2] = {
712 { 0.375000, 0.125000 },
713 { 0.875000, 0.375000 },
714 { 0.125000, 0.625000 },
715 { 0.625000, 0.875000 }
716 };
717 static const float pos8[8][2] = {
718 { 0.562500, 0.312500 },
719 { 0.437500, 0.687500 },
720 { 0.812500, 0.562500 },
721 { 0.312500, 0.187500 },
722 { 0.187500, 0.812500 },
723 { 0.062500, 0.437500 },
724 { 0.687500, 0.937500 },
725 { 0.937500, 0.062500 }
726 };
727 static const float pos16[16][2] = {
728 { 0.187500, 0.062500 },
729 { 0.437500, 0.187500 },
730 { 0.062500, 0.312500 },
731 { 0.312500, 0.437500 },
732 { 0.687500, 0.062500 },
733 { 0.937500, 0.187500 },
734 { 0.562500, 0.312500 },
735 { 0.812500, 0.437500 },
736 { 0.187500, 0.562500 },
737 { 0.437500, 0.687500 },
738 { 0.062500, 0.812500 },
739 { 0.312500, 0.937500 },
740 { 0.687500, 0.562500 },
741 { 0.937500, 0.687500 },
742 { 0.562500, 0.812500 },
743 { 0.812500, 0.937500 }
744 };
745 const float (*positions)[2];
746
747 switch (sample_count) {
748 case 4:
749 positions = pos4;
750 break;
751 case 8:
752 positions = pos8;
753 break;
754 case 16:
755 positions = pos16;
756 break;
757 default:
758 positions = pos1;
759 }
760
761 pos_out[0] = positions[sample_index][0];
762 pos_out[1] = positions[sample_index][1];
763 }
764
765
766 void
svga_init_surface_functions(struct svga_context * svga)767 svga_init_surface_functions(struct svga_context *svga)
768 {
769 svga->pipe.create_surface = svga_create_surface;
770 svga->pipe.surface_destroy = svga_surface_destroy;
771 svga->pipe.get_sample_position = svga_get_sample_position;
772 }
773