gallium/swr: add OpenSWR driver
[mesa.git] / src / gallium / drivers / swr / swr_context.cpp
1 /****************************************************************************
2 * Copyright (C) 2015 Intel Corporation. All Rights Reserved.
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 ***************************************************************************/
23
24 #include "util/u_memory.h"
25 #include "util/u_inlines.h"
26 #include "util/u_format.h"
27
28 extern "C" {
29 #include "util/u_transfer.h"
30 #include "util/u_surface.h"
31 }
32
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
40 #include "api.h"
41 #include "backend.h"
42
43 static struct pipe_surface *
44 swr_create_surface(struct pipe_context *pipe,
45 struct pipe_resource *pt,
46 const struct pipe_surface *surf_tmpl)
47 {
48 struct pipe_surface *ps;
49
50 ps = CALLOC_STRUCT(pipe_surface);
51 if (ps) {
52 pipe_reference_init(&ps->reference, 1);
53 pipe_resource_reference(&ps->texture, pt);
54 ps->context = pipe;
55 ps->format = surf_tmpl->format;
56 if (pt->target != PIPE_BUFFER) {
57 assert(surf_tmpl->u.tex.level <= pt->last_level);
58 ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
59 ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
60 ps->u.tex.level = surf_tmpl->u.tex.level;
61 ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
62 ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
63 if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
64 debug_printf("creating surface with multiple layers, rendering "
65 "to first layer only\n");
66 }
67 } else {
68 /* setting width as number of elements should get us correct
69 * renderbuffer width */
70 ps->width = surf_tmpl->u.buf.last_element
71 - surf_tmpl->u.buf.first_element + 1;
72 ps->height = pt->height0;
73 ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
74 ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
75 assert(ps->u.buf.first_element <= ps->u.buf.last_element);
76 assert(ps->u.buf.last_element < ps->width);
77 }
78 }
79 return ps;
80 }
81
82 static void
83 swr_surface_destroy(struct pipe_context *pipe, struct pipe_surface *surf)
84 {
85 assert(surf->texture);
86 struct pipe_resource *resource = surf->texture;
87
88 /* If the surface being destroyed is a current render target,
89 * call StoreTiles to resolve the hotTile state then set attachment
90 * to NULL.
91 */
92 if (resource->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL
93 | PIPE_BIND_DISPLAY_TARGET)) {
94 struct swr_context *ctx = swr_context(pipe);
95 struct swr_resource *spr = swr_resource(resource);
96 swr_draw_context *pDC = &ctx->swrDC;
97 SWR_SURFACE_STATE *renderTargets = pDC->renderTargets;
98 for (uint32_t i = 0; i < SWR_NUM_ATTACHMENTS; i++)
99 if (renderTargets[i].pBaseAddress == spr->swr.pBaseAddress) {
100 swr_store_render_target(ctx, i, SWR_TILE_RESOLVED);
101
102 /*
103 * Mesa thinks depth/stencil are fused, so we'll never get an
104 * explicit resource for stencil. So, if checking depth, then
105 * also check for stencil.
106 */
107 if (spr->has_stencil && (i == SWR_ATTACHMENT_DEPTH)) {
108 swr_store_render_target(
109 ctx, SWR_ATTACHMENT_STENCIL, SWR_TILE_RESOLVED);
110 }
111
112 SwrWaitForIdle(ctx->swrContext);
113 break;
114 }
115 }
116
117 pipe_resource_reference(&surf->texture, NULL);
118 FREE(surf);
119 }
120
121
122 static void *
123 swr_transfer_map(struct pipe_context *pipe,
124 struct pipe_resource *resource,
125 unsigned level,
126 unsigned usage,
127 const struct pipe_box *box,
128 struct pipe_transfer **transfer)
129 {
130 struct swr_resource *spr = swr_resource(resource);
131 struct pipe_transfer *pt;
132 enum pipe_format format = resource->format;
133
134 assert(resource);
135 assert(level <= resource->last_level);
136
137 /*
138 * If mapping any attached rendertarget, store tiles and wait for idle
139 * before giving CPU access to the surface.
140 * (set postStoreTileState to SWR_TILE_INVALID so tiles are reloaded)
141 */
142 if (resource->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL
143 | PIPE_BIND_DISPLAY_TARGET)) {
144 struct swr_context *ctx = swr_context(pipe);
145 swr_draw_context *pDC = &ctx->swrDC;
146 SWR_SURFACE_STATE *renderTargets = pDC->renderTargets;
147 for (uint32_t i = 0; i < SWR_NUM_ATTACHMENTS; i++)
148 if (renderTargets[i].pBaseAddress == spr->swr.pBaseAddress) {
149 swr_store_render_target(ctx, i, SWR_TILE_INVALID);
150 /*
151 * Mesa thinks depth/stencil are fused, so we'll never get an
152 * explicit map for stencil. So, if mapping depth, then also
153 * store tile for stencil.
154 */
155 if (spr->has_stencil && (i == SWR_ATTACHMENT_DEPTH))
156 swr_store_render_target(
157 ctx, SWR_ATTACHMENT_STENCIL, SWR_TILE_INVALID);
158 SwrWaitForIdle(ctx->swrContext);
159 break;
160 }
161 }
162
163 pt = CALLOC_STRUCT(pipe_transfer);
164 if (!pt)
165 return NULL;
166 pipe_resource_reference(&pt->resource, resource);
167 pt->level = level;
168 pt->box = *box;
169 pt->stride = spr->row_stride[level];
170 pt->layer_stride = spr->img_stride[level];
171
172 /* if we're mapping the depth/stencil, copy in stencil */
173 if (spr->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT
174 && spr->has_stencil) {
175 for (unsigned i = 0; i < spr->alignedWidth * spr->alignedHeight; i++) {
176 spr->swr.pBaseAddress[4 * i + 3] = spr->secondary.pBaseAddress[i];
177 }
178 } else if (spr->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
179 && spr->has_stencil) {
180 for (unsigned i = 0; i < spr->alignedWidth * spr->alignedHeight; i++) {
181 spr->swr.pBaseAddress[8 * i + 4] = spr->secondary.pBaseAddress[i];
182 }
183 }
184
185 unsigned offset = box->z * pt->layer_stride + box->y * pt->stride
186 + box->x * util_format_get_blocksize(format);
187
188 *transfer = pt;
189
190 return spr->swr.pBaseAddress + offset + spr->mip_offsets[level];
191 }
192
193 static void
194 swr_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer)
195 {
196 assert(transfer->resource);
197
198 /*
199 * XXX TODO: use fences and come up with a real resource manager.
200 *
201 * If this resource has been mapped/unmapped, it's probably in use. Tag it
202 *with this context so
203 * we'll know to check dependencies when it's deleted.
204 */
205 struct swr_resource *res = swr_resource(transfer->resource);
206 res->bound_to_context = (void *)pipe;
207
208 /* if we're mapping the depth/stencil, copy out stencil */
209 if (res->base.format == PIPE_FORMAT_Z24_UNORM_S8_UINT
210 && res->has_stencil) {
211 for (unsigned i = 0; i < res->alignedWidth * res->alignedHeight; i++) {
212 res->secondary.pBaseAddress[i] = res->swr.pBaseAddress[4 * i + 3];
213 }
214 } else if (res->base.format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
215 && res->has_stencil) {
216 for (unsigned i = 0; i < res->alignedWidth * res->alignedHeight; i++) {
217 res->secondary.pBaseAddress[i] = res->swr.pBaseAddress[8 * i + 4];
218 }
219 }
220
221 pipe_resource_reference(&transfer->resource, NULL);
222 FREE(transfer);
223 }
224
225
226 static void
227 swr_resource_copy(struct pipe_context *pipe,
228 struct pipe_resource *dst,
229 unsigned dst_level,
230 unsigned dstx,
231 unsigned dsty,
232 unsigned dstz,
233 struct pipe_resource *src,
234 unsigned src_level,
235 const struct pipe_box *src_box)
236 {
237 if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER)
238 || (dst->target != PIPE_BUFFER && src->target != PIPE_BUFFER)) {
239 util_resource_copy_region(
240 pipe, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box);
241 return;
242 }
243
244 debug_printf("unhandled swr_resource_copy\n");
245 }
246
247
248 static void
249 swr_blit(struct pipe_context *pipe, const struct pipe_blit_info *blit_info)
250 {
251 struct swr_context *ctx = swr_context(pipe);
252 struct pipe_blit_info info = *blit_info;
253
254 if (blit_info->render_condition_enable && !swr_check_render_cond(pipe))
255 return;
256
257 if (info.src.resource->nr_samples > 1 && info.dst.resource->nr_samples <= 1
258 && !util_format_is_depth_or_stencil(info.src.resource->format)
259 && !util_format_is_pure_integer(info.src.resource->format)) {
260 debug_printf("swr: color resolve unimplemented\n");
261 return;
262 }
263
264 if (util_try_blit_via_copy_region(pipe, &info)) {
265 return; /* done */
266 }
267
268 if (info.mask & PIPE_MASK_S) {
269 debug_printf("swr: cannot blit stencil, skipping\n");
270 info.mask &= ~PIPE_MASK_S;
271 }
272
273 if (!util_blitter_is_blit_supported(ctx->blitter, &info)) {
274 debug_printf("swr: blit unsupported %s -> %s\n",
275 util_format_short_name(info.src.resource->format),
276 util_format_short_name(info.dst.resource->format));
277 return;
278 }
279
280 /* XXX turn off occlusion and streamout queries */
281
282 util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffer);
283 util_blitter_save_vertex_elements(ctx->blitter, (void *)ctx->velems);
284 util_blitter_save_vertex_shader(ctx->blitter, (void *)ctx->vs);
285 /*util_blitter_save_geometry_shader(ctx->blitter, (void*)ctx->gs);*/
286 util_blitter_save_so_targets(
287 ctx->blitter,
288 ctx->num_so_targets,
289 (struct pipe_stream_output_target **)ctx->so_targets);
290 util_blitter_save_rasterizer(ctx->blitter, (void *)ctx->rasterizer);
291 util_blitter_save_viewport(ctx->blitter, &ctx->viewport);
292 util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
293 util_blitter_save_fragment_shader(ctx->blitter, ctx->fs);
294 util_blitter_save_blend(ctx->blitter, (void *)ctx->blend);
295 util_blitter_save_depth_stencil_alpha(ctx->blitter,
296 (void *)ctx->depth_stencil);
297 util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
298 util_blitter_save_sample_mask(ctx->blitter, ctx->sample_mask);
299 util_blitter_save_framebuffer(ctx->blitter, &ctx->framebuffer);
300 util_blitter_save_fragment_sampler_states(
301 ctx->blitter,
302 ctx->num_samplers[PIPE_SHADER_FRAGMENT],
303 (void **)ctx->samplers[PIPE_SHADER_FRAGMENT]);
304 util_blitter_save_fragment_sampler_views(
305 ctx->blitter,
306 ctx->num_sampler_views[PIPE_SHADER_FRAGMENT],
307 ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
308 util_blitter_save_render_condition(ctx->blitter,
309 ctx->render_cond_query,
310 ctx->render_cond_cond,
311 ctx->render_cond_mode);
312
313 util_blitter_blit(ctx->blitter, &info);
314 }
315
316
317 static void
318 swr_destroy(struct pipe_context *pipe)
319 {
320 struct swr_context *ctx = swr_context(pipe);
321
322 if (ctx->blitter)
323 util_blitter_destroy(ctx->blitter);
324
325 if (ctx->swrContext)
326 SwrDestroyContext(ctx->swrContext);
327
328 delete ctx->blendJIT;
329
330 swr_destroy_scratch_buffers(ctx);
331
332 FREE(ctx);
333 }
334
335
336 static void
337 swr_render_condition(struct pipe_context *pipe,
338 struct pipe_query *query,
339 boolean condition,
340 uint mode)
341 {
342 struct swr_context *ctx = swr_context(pipe);
343
344 ctx->render_cond_query = query;
345 ctx->render_cond_mode = mode;
346 ctx->render_cond_cond = condition;
347 }
348
349
350 struct pipe_context *
351 swr_create_context(struct pipe_screen *screen, void *priv, unsigned flags)
352 {
353 struct swr_context *ctx = CALLOC_STRUCT(swr_context);
354 ctx->blendJIT =
355 new std::unordered_map<BLEND_COMPILE_STATE, PFN_BLEND_JIT_FUNC>;
356
357 SWR_CREATECONTEXT_INFO createInfo;
358 createInfo.driver = GL;
359 createInfo.privateStateSize = sizeof(swr_draw_context);
360 createInfo.maxSubContexts = 0;
361 createInfo.pfnLoadTile = swr_LoadHotTile;
362 createInfo.pfnStoreTile = swr_StoreHotTile;
363 createInfo.pfnClearTile = swr_StoreHotTileClear;
364 ctx->swrContext = SwrCreateContext(&createInfo);
365
366 /* Init Load/Store/ClearTiles Tables */
367 swr_InitMemoryModule();
368
369 InitBackendFuncTables();
370
371 if (ctx->swrContext == NULL)
372 goto fail;
373
374 ctx->pipe.screen = screen;
375 ctx->pipe.destroy = swr_destroy;
376 ctx->pipe.priv = priv;
377 ctx->pipe.create_surface = swr_create_surface;
378 ctx->pipe.surface_destroy = swr_surface_destroy;
379 ctx->pipe.transfer_map = swr_transfer_map;
380 ctx->pipe.transfer_unmap = swr_transfer_unmap;
381
382 ctx->pipe.transfer_flush_region = u_default_transfer_flush_region;
383 ctx->pipe.transfer_inline_write = u_default_transfer_inline_write;
384
385 ctx->pipe.resource_copy_region = swr_resource_copy;
386 ctx->pipe.render_condition = swr_render_condition;
387
388 swr_state_init(&ctx->pipe);
389 swr_clear_init(&ctx->pipe);
390 swr_draw_init(&ctx->pipe);
391 swr_query_init(&ctx->pipe);
392
393 ctx->pipe.blit = swr_blit;
394 ctx->blitter = util_blitter_create(&ctx->pipe);
395 if (!ctx->blitter) {
396 goto fail;
397 }
398
399 swr_init_scratch_buffers(ctx);
400
401 return &ctx->pipe;
402
403 fail:
404 /* Should really validate the init steps and fail gracefully */
405 swr_destroy(&ctx->pipe);
406 return NULL;
407 }