1 /****************************************************************************
2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 ***************************************************************************/
24 #include "util/u_memory.h"
25 #include "util/u_inlines.h"
26 #include "util/u_format.h"
29 #include "util/u_transfer.h"
30 #include "util/u_surface.h"
33 #include "swr_context.h"
34 #include "swr_memory.h"
35 #include "swr_screen.h"
36 #include "swr_resource.h"
37 #include "swr_scratch.h"
38 #include "swr_query.h"
39 #include "swr_fence.h"
44 static struct pipe_surface
*
45 swr_create_surface(struct pipe_context
*pipe
,
46 struct pipe_resource
*pt
,
47 const struct pipe_surface
*surf_tmpl
)
49 struct pipe_surface
*ps
;
51 ps
= CALLOC_STRUCT(pipe_surface
);
53 pipe_reference_init(&ps
->reference
, 1);
54 pipe_resource_reference(&ps
->texture
, pt
);
56 ps
->format
= surf_tmpl
->format
;
57 if (pt
->target
!= PIPE_BUFFER
) {
58 assert(surf_tmpl
->u
.tex
.level
<= pt
->last_level
);
59 ps
->width
= u_minify(pt
->width0
, surf_tmpl
->u
.tex
.level
);
60 ps
->height
= u_minify(pt
->height0
, surf_tmpl
->u
.tex
.level
);
61 ps
->u
.tex
.level
= surf_tmpl
->u
.tex
.level
;
62 ps
->u
.tex
.first_layer
= surf_tmpl
->u
.tex
.first_layer
;
63 ps
->u
.tex
.last_layer
= surf_tmpl
->u
.tex
.last_layer
;
64 if (ps
->u
.tex
.first_layer
!= ps
->u
.tex
.last_layer
) {
65 debug_printf("creating surface with multiple layers, rendering "
66 "to first layer only\n");
69 /* setting width as number of elements should get us correct
70 * renderbuffer width */
71 ps
->width
= surf_tmpl
->u
.buf
.last_element
72 - surf_tmpl
->u
.buf
.first_element
+ 1;
73 ps
->height
= pt
->height0
;
74 ps
->u
.buf
.first_element
= surf_tmpl
->u
.buf
.first_element
;
75 ps
->u
.buf
.last_element
= surf_tmpl
->u
.buf
.last_element
;
76 assert(ps
->u
.buf
.first_element
<= ps
->u
.buf
.last_element
);
77 assert(ps
->u
.buf
.last_element
< ps
->width
);
84 swr_surface_destroy(struct pipe_context
*pipe
, struct pipe_surface
*surf
)
86 assert(surf
->texture
);
87 struct pipe_resource
*resource
= surf
->texture
;
89 /* If the resource has been drawn to, store tiles. */
90 swr_store_dirty_resource(pipe
, resource
, SWR_TILE_RESOLVED
);
92 pipe_resource_reference(&resource
, NULL
);
98 swr_transfer_map(struct pipe_context
*pipe
,
99 struct pipe_resource
*resource
,
102 const struct pipe_box
*box
,
103 struct pipe_transfer
**transfer
)
105 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
106 struct swr_resource
*spr
= swr_resource(resource
);
107 struct pipe_transfer
*pt
;
108 enum pipe_format format
= resource
->format
;
111 assert(level
<= resource
->last_level
);
113 /* If mapping an attached rendertarget, store tiles to surface and set
114 * postStoreTileState to SWR_TILE_INVALID so tiles get reloaded on next use
115 * and nothing needs to be done at unmap. */
116 swr_store_dirty_resource(pipe
, resource
, SWR_TILE_INVALID
);
118 if (!(usage
& PIPE_TRANSFER_UNSYNCHRONIZED
)) {
119 /* If resource is in use, finish fence before mapping.
120 * Unless requested not to block, then if not done return NULL map */
121 if (usage
& PIPE_TRANSFER_DONTBLOCK
) {
122 if (swr_is_fence_pending(screen
->flush_fence
))
126 /* But, if there's no fence pending, submit one.
127 * XXX: Remove once draw timestamps are finished. */
128 if (!swr_is_fence_pending(screen
->flush_fence
))
129 swr_fence_submit(swr_context(pipe
), screen
->flush_fence
);
131 swr_fence_finish(pipe
->screen
, screen
->flush_fence
, 0);
132 swr_resource_unused(resource
);
137 pt
= CALLOC_STRUCT(pipe_transfer
);
140 pipe_resource_reference(&pt
->resource
, resource
);
143 pt
->stride
= spr
->row_stride
[level
];
144 pt
->layer_stride
= spr
->img_stride
[level
];
146 /* if we're mapping the depth/stencil, copy in stencil */
147 if (spr
->base
.format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
148 && spr
->has_stencil
) {
149 for (unsigned i
= 0; i
< spr
->alignedWidth
* spr
->alignedHeight
; i
++) {
150 spr
->swr
.pBaseAddress
[4 * i
+ 3] = spr
->secondary
.pBaseAddress
[i
];
152 } else if (spr
->base
.format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
153 && spr
->has_stencil
) {
154 for (unsigned i
= 0; i
< spr
->alignedWidth
* spr
->alignedHeight
; i
++) {
155 spr
->swr
.pBaseAddress
[8 * i
+ 4] = spr
->secondary
.pBaseAddress
[i
];
159 unsigned offset
= box
->z
* pt
->layer_stride
+ box
->y
* pt
->stride
160 + box
->x
* util_format_get_blocksize(format
);
164 return spr
->swr
.pBaseAddress
+ offset
+ spr
->mip_offsets
[level
];
168 swr_transfer_unmap(struct pipe_context
*pipe
, struct pipe_transfer
*transfer
)
170 assert(transfer
->resource
);
172 struct swr_resource
*res
= swr_resource(transfer
->resource
);
173 /* if we're mapping the depth/stencil, copy out stencil */
174 if (res
->base
.format
== PIPE_FORMAT_Z24_UNORM_S8_UINT
175 && res
->has_stencil
) {
176 for (unsigned i
= 0; i
< res
->alignedWidth
* res
->alignedHeight
; i
++) {
177 res
->secondary
.pBaseAddress
[i
] = res
->swr
.pBaseAddress
[4 * i
+ 3];
179 } else if (res
->base
.format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
180 && res
->has_stencil
) {
181 for (unsigned i
= 0; i
< res
->alignedWidth
* res
->alignedHeight
; i
++) {
182 res
->secondary
.pBaseAddress
[i
] = res
->swr
.pBaseAddress
[8 * i
+ 4];
186 pipe_resource_reference(&transfer
->resource
, NULL
);
192 swr_resource_copy(struct pipe_context
*pipe
,
193 struct pipe_resource
*dst
,
198 struct pipe_resource
*src
,
200 const struct pipe_box
*src_box
)
202 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
204 /* If either the src or dst is a renderTarget, store tiles before copy */
205 swr_store_dirty_resource(pipe
, src
, SWR_TILE_RESOLVED
);
206 swr_store_dirty_resource(pipe
, dst
, SWR_TILE_RESOLVED
);
208 swr_fence_finish(pipe
->screen
, screen
->flush_fence
, 0);
209 swr_resource_unused(src
);
210 swr_resource_unused(dst
);
212 if ((dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
)
213 || (dst
->target
!= PIPE_BUFFER
&& src
->target
!= PIPE_BUFFER
)) {
214 util_resource_copy_region(
215 pipe
, dst
, dst_level
, dstx
, dsty
, dstz
, src
, src_level
, src_box
);
219 debug_printf("unhandled swr_resource_copy\n");
224 swr_blit(struct pipe_context
*pipe
, const struct pipe_blit_info
*blit_info
)
226 struct swr_context
*ctx
= swr_context(pipe
);
227 struct pipe_blit_info info
= *blit_info
;
229 if (blit_info
->render_condition_enable
&& !swr_check_render_cond(pipe
))
232 if (info
.src
.resource
->nr_samples
> 1 && info
.dst
.resource
->nr_samples
<= 1
233 && !util_format_is_depth_or_stencil(info
.src
.resource
->format
)
234 && !util_format_is_pure_integer(info
.src
.resource
->format
)) {
235 debug_printf("swr: color resolve unimplemented\n");
239 if (util_try_blit_via_copy_region(pipe
, &info
)) {
243 if (info
.mask
& PIPE_MASK_S
) {
244 debug_printf("swr: cannot blit stencil, skipping\n");
245 info
.mask
&= ~PIPE_MASK_S
;
248 if (!util_blitter_is_blit_supported(ctx
->blitter
, &info
)) {
249 debug_printf("swr: blit unsupported %s -> %s\n",
250 util_format_short_name(info
.src
.resource
->format
),
251 util_format_short_name(info
.dst
.resource
->format
));
255 /* XXX turn off occlusion and streamout queries */
257 util_blitter_save_vertex_buffer_slot(ctx
->blitter
, ctx
->vertex_buffer
);
258 util_blitter_save_vertex_elements(ctx
->blitter
, (void *)ctx
->velems
);
259 util_blitter_save_vertex_shader(ctx
->blitter
, (void *)ctx
->vs
);
260 /*util_blitter_save_geometry_shader(ctx->blitter, (void*)ctx->gs);*/
261 util_blitter_save_so_targets(
264 (struct pipe_stream_output_target
**)ctx
->so_targets
);
265 util_blitter_save_rasterizer(ctx
->blitter
, (void *)ctx
->rasterizer
);
266 util_blitter_save_viewport(ctx
->blitter
, &ctx
->viewport
);
267 util_blitter_save_scissor(ctx
->blitter
, &ctx
->scissor
);
268 util_blitter_save_fragment_shader(ctx
->blitter
, ctx
->fs
);
269 util_blitter_save_blend(ctx
->blitter
, (void *)ctx
->blend
);
270 util_blitter_save_depth_stencil_alpha(ctx
->blitter
,
271 (void *)ctx
->depth_stencil
);
272 util_blitter_save_stencil_ref(ctx
->blitter
, &ctx
->stencil_ref
);
273 util_blitter_save_sample_mask(ctx
->blitter
, ctx
->sample_mask
);
274 util_blitter_save_framebuffer(ctx
->blitter
, &ctx
->framebuffer
);
275 util_blitter_save_fragment_sampler_states(
277 ctx
->num_samplers
[PIPE_SHADER_FRAGMENT
],
278 (void **)ctx
->samplers
[PIPE_SHADER_FRAGMENT
]);
279 util_blitter_save_fragment_sampler_views(
281 ctx
->num_sampler_views
[PIPE_SHADER_FRAGMENT
],
282 ctx
->sampler_views
[PIPE_SHADER_FRAGMENT
]);
283 util_blitter_save_render_condition(ctx
->blitter
,
284 ctx
->render_cond_query
,
285 ctx
->render_cond_cond
,
286 ctx
->render_cond_mode
);
288 util_blitter_blit(ctx
->blitter
, &info
);
293 swr_destroy(struct pipe_context
*pipe
)
295 struct swr_context
*ctx
= swr_context(pipe
);
296 struct swr_screen
*screen
= swr_screen(pipe
->screen
);
299 util_blitter_destroy(ctx
->blitter
);
301 /* Idle core before deleting context */
302 SwrWaitForIdle(ctx
->swrContext
);
304 for (unsigned i
= 0; i
< PIPE_MAX_COLOR_BUFS
; i
++) {
305 pipe_surface_reference(&ctx
->framebuffer
.cbufs
[i
], NULL
);
308 pipe_surface_reference(&ctx
->framebuffer
.zsbuf
, NULL
);
310 for (unsigned i
= 0; i
< Elements(ctx
->sampler_views
[0]); i
++) {
311 pipe_sampler_view_reference(&ctx
->sampler_views
[PIPE_SHADER_FRAGMENT
][i
], NULL
);
314 for (unsigned i
= 0; i
< Elements(ctx
->sampler_views
[0]); i
++) {
315 pipe_sampler_view_reference(&ctx
->sampler_views
[PIPE_SHADER_VERTEX
][i
], NULL
);
319 SwrDestroyContext(ctx
->swrContext
);
321 delete ctx
->blendJIT
;
323 swr_destroy_scratch_buffers(ctx
);
333 swr_render_condition(struct pipe_context
*pipe
,
334 struct pipe_query
*query
,
338 struct swr_context
*ctx
= swr_context(pipe
);
340 ctx
->render_cond_query
= query
;
341 ctx
->render_cond_mode
= mode
;
342 ctx
->render_cond_cond
= condition
;
345 struct pipe_context
*
346 swr_create_context(struct pipe_screen
*p_screen
, void *priv
, unsigned flags
)
348 struct swr_context
*ctx
= CALLOC_STRUCT(swr_context
);
349 struct swr_screen
*screen
= swr_screen(p_screen
);
351 new std::unordered_map
<BLEND_COMPILE_STATE
, PFN_BLEND_JIT_FUNC
>;
353 SWR_CREATECONTEXT_INFO createInfo
;
354 createInfo
.driver
= GL
;
355 createInfo
.privateStateSize
= sizeof(swr_draw_context
);
356 createInfo
.pfnLoadTile
= swr_LoadHotTile
;
357 createInfo
.pfnStoreTile
= swr_StoreHotTile
;
358 createInfo
.pfnClearTile
= swr_StoreHotTileClear
;
359 ctx
->swrContext
= SwrCreateContext(&createInfo
);
361 /* Init Load/Store/ClearTiles Tables */
362 swr_InitMemoryModule();
364 InitBackendFuncTables();
366 if (ctx
->swrContext
== NULL
)
369 screen
->pipe
= &ctx
->pipe
;
370 ctx
->pipe
.screen
= p_screen
;
371 ctx
->pipe
.destroy
= swr_destroy
;
372 ctx
->pipe
.priv
= priv
;
373 ctx
->pipe
.create_surface
= swr_create_surface
;
374 ctx
->pipe
.surface_destroy
= swr_surface_destroy
;
375 ctx
->pipe
.transfer_map
= swr_transfer_map
;
376 ctx
->pipe
.transfer_unmap
= swr_transfer_unmap
;
378 ctx
->pipe
.transfer_flush_region
= u_default_transfer_flush_region
;
379 ctx
->pipe
.transfer_inline_write
= u_default_transfer_inline_write
;
381 ctx
->pipe
.resource_copy_region
= swr_resource_copy
;
382 ctx
->pipe
.render_condition
= swr_render_condition
;
384 swr_state_init(&ctx
->pipe
);
385 swr_clear_init(&ctx
->pipe
);
386 swr_draw_init(&ctx
->pipe
);
387 swr_query_init(&ctx
->pipe
);
389 ctx
->pipe
.blit
= swr_blit
;
390 ctx
->blitter
= util_blitter_create(&ctx
->pipe
);
394 swr_init_scratch_buffers(ctx
);
399 /* Should really validate the init steps and fail gracefully */
400 swr_destroy(&ctx
->pipe
);