gallium/ddebug: add GALLIUM_DDEBUG_SKIP option
[mesa.git] / src / gallium / drivers / ddebug / dd_draw.c
1 /**************************************************************************
2 *
3 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Copyright 2008 VMware, Inc.
5 * All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * on the rights to use, copy, modify, merge, publish, distribute, sub
11 * license, and/or sell copies of the Software, and to permit persons to whom
12 * the Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
16 * Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "dd_pipe.h"
29
30 #include "util/u_dump.h"
31 #include "util/u_format.h"
32 #include "tgsi/tgsi_scan.h"
33
34
35 enum call_type
36 {
37 CALL_DRAW_VBO,
38 CALL_RESOURCE_COPY_REGION,
39 CALL_BLIT,
40 CALL_FLUSH_RESOURCE,
41 CALL_CLEAR,
42 CALL_CLEAR_BUFFER,
43 CALL_CLEAR_RENDER_TARGET,
44 CALL_CLEAR_DEPTH_STENCIL,
45 };
46
47 struct call_resource_copy_region
48 {
49 struct pipe_resource *dst;
50 unsigned dst_level;
51 unsigned dstx, dsty, dstz;
52 struct pipe_resource *src;
53 unsigned src_level;
54 const struct pipe_box *src_box;
55 };
56
57 struct call_clear
58 {
59 unsigned buffers;
60 const union pipe_color_union *color;
61 double depth;
62 unsigned stencil;
63 };
64
65 struct call_clear_buffer
66 {
67 struct pipe_resource *res;
68 unsigned offset;
69 unsigned size;
70 const void *clear_value;
71 int clear_value_size;
72 };
73
74 struct dd_call
75 {
76 enum call_type type;
77
78 union {
79 struct pipe_draw_info draw_vbo;
80 struct call_resource_copy_region resource_copy_region;
81 struct pipe_blit_info blit;
82 struct pipe_resource *flush_resource;
83 struct call_clear clear;
84 struct call_clear_buffer clear_buffer;
85 } info;
86 };
87
88 static FILE *
89 dd_get_file_stream(struct dd_context *dctx)
90 {
91 struct pipe_screen *screen = dctx->pipe->screen;
92 FILE *f = dd_get_debug_file();
93 if (!f)
94 return NULL;
95
96 fprintf(f, "Driver vendor: %s\n", screen->get_vendor(screen));
97 fprintf(f, "Device vendor: %s\n", screen->get_device_vendor(screen));
98 fprintf(f, "Device name: %s\n\n", screen->get_name(screen));
99 return f;
100 }
101
102 static void
103 dd_close_file_stream(FILE *f)
104 {
105 fclose(f);
106 }
107
108 static unsigned
109 dd_num_active_viewports(struct dd_context *dctx)
110 {
111 struct tgsi_shader_info info;
112 const struct tgsi_token *tokens;
113
114 if (dctx->shaders[PIPE_SHADER_GEOMETRY])
115 tokens = dctx->shaders[PIPE_SHADER_GEOMETRY]->state.shader.tokens;
116 else if (dctx->shaders[PIPE_SHADER_TESS_EVAL])
117 tokens = dctx->shaders[PIPE_SHADER_TESS_EVAL]->state.shader.tokens;
118 else if (dctx->shaders[PIPE_SHADER_VERTEX])
119 tokens = dctx->shaders[PIPE_SHADER_VERTEX]->state.shader.tokens;
120 else
121 return 1;
122
123 tgsi_scan_shader(tokens, &info);
124 return info.writes_viewport_index ? PIPE_MAX_VIEWPORTS : 1;
125 }
126
127 #define COLOR_RESET "\033[0m"
128 #define COLOR_SHADER "\033[1;32m"
129 #define COLOR_STATE "\033[1;33m"
130
131 #define DUMP(name, var) do { \
132 fprintf(f, COLOR_STATE #name ": " COLOR_RESET); \
133 util_dump_##name(f, var); \
134 fprintf(f, "\n"); \
135 } while(0)
136
137 #define DUMP_I(name, var, i) do { \
138 fprintf(f, COLOR_STATE #name " %i: " COLOR_RESET, i); \
139 util_dump_##name(f, var); \
140 fprintf(f, "\n"); \
141 } while(0)
142
143 #define DUMP_M(name, var, member) do { \
144 fprintf(f, " " #member ": "); \
145 util_dump_##name(f, (var)->member); \
146 fprintf(f, "\n"); \
147 } while(0)
148
149 #define DUMP_M_ADDR(name, var, member) do { \
150 fprintf(f, " " #member ": "); \
151 util_dump_##name(f, &(var)->member); \
152 fprintf(f, "\n"); \
153 } while(0)
154
155 static void
156 print_named_value(FILE *f, const char *name, int value)
157 {
158 fprintf(f, COLOR_STATE "%s" COLOR_RESET " = %i\n", name, value);
159 }
160
161 static void
162 print_named_xvalue(FILE *f, const char *name, int value)
163 {
164 fprintf(f, COLOR_STATE "%s" COLOR_RESET " = 0x%08x\n", name, value);
165 }
166
167 static void
168 util_dump_uint(FILE *f, unsigned i)
169 {
170 fprintf(f, "%u", i);
171 }
172
173 static void
174 util_dump_hex(FILE *f, unsigned i)
175 {
176 fprintf(f, "0x%x", i);
177 }
178
179 static void
180 util_dump_double(FILE *f, double d)
181 {
182 fprintf(f, "%f", d);
183 }
184
185 static void
186 util_dump_format(FILE *f, enum pipe_format format)
187 {
188 fprintf(f, "%s", util_format_name(format));
189 }
190
191 static void
192 util_dump_color_union(FILE *f, const union pipe_color_union *color)
193 {
194 fprintf(f, "{f = {%f, %f, %f, %f}, ui = {%u, %u, %u, %u}",
195 color->f[0], color->f[1], color->f[2], color->f[3],
196 color->ui[0], color->ui[1], color->ui[2], color->ui[3]);
197 }
198
199 static void
200 util_dump_query(FILE *f, struct dd_query *query)
201 {
202 if (query->type >= PIPE_QUERY_DRIVER_SPECIFIC)
203 fprintf(f, "PIPE_QUERY_DRIVER_SPECIFIC + %i",
204 query->type - PIPE_QUERY_DRIVER_SPECIFIC);
205 else
206 fprintf(f, "%s", util_dump_query_type(query->type, false));
207 }
208
209 static void
210 dd_dump_render_condition(struct dd_context *dctx, FILE *f)
211 {
212 if (dctx->render_cond.query) {
213 fprintf(f, "render condition:\n");
214 DUMP_M(query, &dctx->render_cond, query);
215 DUMP_M(uint, &dctx->render_cond, condition);
216 DUMP_M(uint, &dctx->render_cond, mode);
217 fprintf(f, "\n");
218 }
219 }
220
221 static void
222 dd_dump_draw_vbo(struct dd_context *dctx, struct pipe_draw_info *info, FILE *f)
223 {
224 int sh, i;
225 const char *shader_str[PIPE_SHADER_TYPES];
226
227 shader_str[PIPE_SHADER_VERTEX] = "VERTEX";
228 shader_str[PIPE_SHADER_TESS_CTRL] = "TESS_CTRL";
229 shader_str[PIPE_SHADER_TESS_EVAL] = "TESS_EVAL";
230 shader_str[PIPE_SHADER_GEOMETRY] = "GEOMETRY";
231 shader_str[PIPE_SHADER_FRAGMENT] = "FRAGMENT";
232 shader_str[PIPE_SHADER_COMPUTE] = "COMPUTE";
233
234 DUMP(draw_info, info);
235 if (info->indexed) {
236 DUMP(index_buffer, &dctx->index_buffer);
237 if (dctx->index_buffer.buffer)
238 DUMP_M(resource, &dctx->index_buffer, buffer);
239 }
240 if (info->count_from_stream_output)
241 DUMP_M(stream_output_target, info,
242 count_from_stream_output);
243 if (info->indirect)
244 DUMP_M(resource, info, indirect);
245 fprintf(f, "\n");
246
247 /* TODO: dump active queries */
248
249 dd_dump_render_condition(dctx, f);
250
251 for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
252 if (dctx->vertex_buffers[i].buffer ||
253 dctx->vertex_buffers[i].user_buffer) {
254 DUMP_I(vertex_buffer, &dctx->vertex_buffers[i], i);
255 if (dctx->vertex_buffers[i].buffer)
256 DUMP_M(resource, &dctx->vertex_buffers[i], buffer);
257 }
258
259 if (dctx->velems) {
260 print_named_value(f, "num vertex elements",
261 dctx->velems->state.velems.count);
262 for (i = 0; i < dctx->velems->state.velems.count; i++) {
263 fprintf(f, " ");
264 DUMP_I(vertex_element, &dctx->velems->state.velems.velems[i], i);
265 }
266 }
267
268 print_named_value(f, "num stream output targets", dctx->num_so_targets);
269 for (i = 0; i < dctx->num_so_targets; i++)
270 if (dctx->so_targets[i]) {
271 DUMP_I(stream_output_target, dctx->so_targets[i], i);
272 DUMP_M(resource, dctx->so_targets[i], buffer);
273 fprintf(f, " offset = %i\n", dctx->so_offsets[i]);
274 }
275
276 fprintf(f, "\n");
277 for (sh = 0; sh < PIPE_SHADER_TYPES; sh++) {
278 if (sh == PIPE_SHADER_COMPUTE)
279 continue;
280
281 if (sh == PIPE_SHADER_TESS_CTRL &&
282 !dctx->shaders[PIPE_SHADER_TESS_CTRL] &&
283 dctx->shaders[PIPE_SHADER_TESS_EVAL])
284 fprintf(f, "tess_state: {default_outer_level = {%f, %f, %f, %f}, "
285 "default_inner_level = {%f, %f}}\n",
286 dctx->tess_default_levels[0],
287 dctx->tess_default_levels[1],
288 dctx->tess_default_levels[2],
289 dctx->tess_default_levels[3],
290 dctx->tess_default_levels[4],
291 dctx->tess_default_levels[5]);
292
293 if (sh == PIPE_SHADER_FRAGMENT)
294 if (dctx->rs) {
295 unsigned num_viewports = dd_num_active_viewports(dctx);
296
297 if (dctx->rs->state.rs.clip_plane_enable)
298 DUMP(clip_state, &dctx->clip_state);
299
300 for (i = 0; i < num_viewports; i++)
301 DUMP_I(viewport_state, &dctx->viewports[i], i);
302
303 if (dctx->rs->state.rs.scissor)
304 for (i = 0; i < num_viewports; i++)
305 DUMP_I(scissor_state, &dctx->scissors[i], i);
306
307 DUMP(rasterizer_state, &dctx->rs->state.rs);
308
309 if (dctx->rs->state.rs.poly_stipple_enable)
310 DUMP(poly_stipple, &dctx->polygon_stipple);
311 fprintf(f, "\n");
312 }
313
314 if (!dctx->shaders[sh])
315 continue;
316
317 fprintf(f, COLOR_SHADER "begin shader: %s" COLOR_RESET "\n", shader_str[sh]);
318 DUMP(shader_state, &dctx->shaders[sh]->state.shader);
319
320 for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++)
321 if (dctx->constant_buffers[sh][i].buffer ||
322 dctx->constant_buffers[sh][i].user_buffer) {
323 DUMP_I(constant_buffer, &dctx->constant_buffers[sh][i], i);
324 if (dctx->constant_buffers[sh][i].buffer)
325 DUMP_M(resource, &dctx->constant_buffers[sh][i], buffer);
326 }
327
328 for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
329 if (dctx->sampler_states[sh][i])
330 DUMP_I(sampler_state, &dctx->sampler_states[sh][i]->state.sampler, i);
331
332 for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
333 if (dctx->sampler_views[sh][i]) {
334 DUMP_I(sampler_view, dctx->sampler_views[sh][i], i);
335 DUMP_M(resource, dctx->sampler_views[sh][i], texture);
336 }
337
338 /* TODO: print shader images */
339 /* TODO: print shader buffers */
340
341 fprintf(f, COLOR_SHADER "end shader: %s" COLOR_RESET "\n\n", shader_str[sh]);
342 }
343
344 if (dctx->dsa)
345 DUMP(depth_stencil_alpha_state, &dctx->dsa->state.dsa);
346 DUMP(stencil_ref, &dctx->stencil_ref);
347
348 if (dctx->blend)
349 DUMP(blend_state, &dctx->blend->state.blend);
350 DUMP(blend_color, &dctx->blend_color);
351
352 print_named_value(f, "min_samples", dctx->min_samples);
353 print_named_xvalue(f, "sample_mask", dctx->sample_mask);
354 fprintf(f, "\n");
355
356 DUMP(framebuffer_state, &dctx->framebuffer_state);
357 for (i = 0; i < dctx->framebuffer_state.nr_cbufs; i++)
358 if (dctx->framebuffer_state.cbufs[i]) {
359 fprintf(f, " " COLOR_STATE "cbufs[%i]:" COLOR_RESET "\n ", i);
360 DUMP(surface, dctx->framebuffer_state.cbufs[i]);
361 fprintf(f, " ");
362 DUMP(resource, dctx->framebuffer_state.cbufs[i]->texture);
363 }
364 if (dctx->framebuffer_state.zsbuf) {
365 fprintf(f, " " COLOR_STATE "zsbuf:" COLOR_RESET "\n ");
366 DUMP(surface, dctx->framebuffer_state.zsbuf);
367 fprintf(f, " ");
368 DUMP(resource, dctx->framebuffer_state.zsbuf->texture);
369 }
370 fprintf(f, "\n");
371 }
372
373 static void
374 dd_dump_resource_copy_region(struct dd_context *dctx,
375 struct call_resource_copy_region *info,
376 FILE *f)
377 {
378 fprintf(f, "%s:\n", __func__+8);
379 DUMP_M(resource, info, dst);
380 DUMP_M(uint, info, dst_level);
381 DUMP_M(uint, info, dstx);
382 DUMP_M(uint, info, dsty);
383 DUMP_M(uint, info, dstz);
384 DUMP_M(resource, info, src);
385 DUMP_M(uint, info, src_level);
386 DUMP_M(box, info, src_box);
387 }
388
389 static void
390 dd_dump_blit(struct dd_context *dctx, struct pipe_blit_info *info, FILE *f)
391 {
392 fprintf(f, "%s:\n", __func__+8);
393 DUMP_M(resource, info, dst.resource);
394 DUMP_M(uint, info, dst.level);
395 DUMP_M_ADDR(box, info, dst.box);
396 DUMP_M(format, info, dst.format);
397
398 DUMP_M(resource, info, src.resource);
399 DUMP_M(uint, info, src.level);
400 DUMP_M_ADDR(box, info, src.box);
401 DUMP_M(format, info, src.format);
402
403 DUMP_M(hex, info, mask);
404 DUMP_M(uint, info, filter);
405 DUMP_M(uint, info, scissor_enable);
406 DUMP_M_ADDR(scissor_state, info, scissor);
407 DUMP_M(uint, info, render_condition_enable);
408
409 if (info->render_condition_enable)
410 dd_dump_render_condition(dctx, f);
411 }
412
413 static void
414 dd_dump_flush_resource(struct dd_context *dctx, struct pipe_resource *res,
415 FILE *f)
416 {
417 fprintf(f, "%s:\n", __func__+8);
418 DUMP(resource, res);
419 }
420
421 static void
422 dd_dump_clear(struct dd_context *dctx, struct call_clear *info, FILE *f)
423 {
424 fprintf(f, "%s:\n", __func__+8);
425 DUMP_M(uint, info, buffers);
426 DUMP_M(color_union, info, color);
427 DUMP_M(double, info, depth);
428 DUMP_M(hex, info, stencil);
429 }
430
431 static void
432 dd_dump_clear_buffer(struct dd_context *dctx, struct call_clear_buffer *info,
433 FILE *f)
434 {
435 int i;
436 const char *value = (const char*)info->clear_value;
437
438 fprintf(f, "%s:\n", __func__+8);
439 DUMP_M(resource, info, res);
440 DUMP_M(uint, info, offset);
441 DUMP_M(uint, info, size);
442 DUMP_M(uint, info, clear_value_size);
443
444 fprintf(f, " clear_value:");
445 for (i = 0; i < info->clear_value_size; i++)
446 fprintf(f, " %02x", value[i]);
447 fprintf(f, "\n");
448 }
449
450 static void
451 dd_dump_clear_render_target(struct dd_context *dctx, FILE *f)
452 {
453 fprintf(f, "%s:\n", __func__+8);
454 /* TODO */
455 }
456
457 static void
458 dd_dump_clear_depth_stencil(struct dd_context *dctx, FILE *f)
459 {
460 fprintf(f, "%s:\n", __func__+8);
461 /* TODO */
462 }
463
464 static void
465 dd_dump_driver_state(struct dd_context *dctx, FILE *f, unsigned flags)
466 {
467 if (dctx->pipe->dump_debug_state) {
468 fprintf(f,"\n\n**************************************************"
469 "***************************\n");
470 fprintf(f, "Driver-specific state:\n\n");
471 dctx->pipe->dump_debug_state(dctx->pipe, f, flags);
472 }
473 }
474
475 static void
476 dd_dump_call(struct dd_context *dctx, struct dd_call *call, unsigned flags)
477 {
478 FILE *f = dd_get_file_stream(dctx);
479
480 if (!f)
481 return;
482
483 switch (call->type) {
484 case CALL_DRAW_VBO:
485 dd_dump_draw_vbo(dctx, &call->info.draw_vbo, f);
486 break;
487 case CALL_RESOURCE_COPY_REGION:
488 dd_dump_resource_copy_region(dctx, &call->info.resource_copy_region, f);
489 break;
490 case CALL_BLIT:
491 dd_dump_blit(dctx, &call->info.blit, f);
492 break;
493 case CALL_FLUSH_RESOURCE:
494 dd_dump_flush_resource(dctx, call->info.flush_resource, f);
495 break;
496 case CALL_CLEAR:
497 dd_dump_clear(dctx, &call->info.clear, f);
498 break;
499 case CALL_CLEAR_BUFFER:
500 dd_dump_clear_buffer(dctx, &call->info.clear_buffer, f);
501 break;
502 case CALL_CLEAR_RENDER_TARGET:
503 dd_dump_clear_render_target(dctx, f);
504 break;
505 case CALL_CLEAR_DEPTH_STENCIL:
506 dd_dump_clear_depth_stencil(dctx, f);
507 }
508
509 dd_dump_driver_state(dctx, f, flags);
510 dd_close_file_stream(f);
511 }
512
513 static void
514 dd_kill_process(void)
515 {
516 sync();
517 fprintf(stderr, "dd: Aborting the process...\n");
518 fflush(stdout);
519 fflush(stderr);
520 abort();
521 }
522
523 static bool
524 dd_flush_and_check_hang(struct dd_context *dctx,
525 struct pipe_fence_handle **flush_fence,
526 unsigned flush_flags)
527 {
528 struct pipe_fence_handle *fence = NULL;
529 struct pipe_context *pipe = dctx->pipe;
530 struct pipe_screen *screen = pipe->screen;
531 uint64_t timeout_ms = dd_screen(dctx->base.screen)->timeout_ms;
532 bool idle;
533
534 assert(timeout_ms > 0);
535
536 pipe->flush(pipe, &fence, flush_flags);
537 if (flush_fence)
538 screen->fence_reference(screen, flush_fence, fence);
539 if (!fence)
540 return false;
541
542 idle = screen->fence_finish(screen, fence, timeout_ms * 1000000);
543 screen->fence_reference(screen, &fence, NULL);
544 if (!idle)
545 fprintf(stderr, "dd: GPU hang detected!\n");
546 return !idle;
547 }
548
549 static void
550 dd_flush_and_handle_hang(struct dd_context *dctx,
551 struct pipe_fence_handle **fence, unsigned flags,
552 const char *cause)
553 {
554 if (dd_flush_and_check_hang(dctx, fence, flags)) {
555 FILE *f = dd_get_file_stream(dctx);
556
557 if (f) {
558 fprintf(f, "dd: %s.\n", cause);
559 dd_dump_driver_state(dctx, f, PIPE_DEBUG_DEVICE_IS_HUNG);
560 dd_close_file_stream(f);
561 }
562
563 /* Terminate the process to prevent future hangs. */
564 dd_kill_process();
565 }
566 }
567
568 static void
569 dd_context_flush(struct pipe_context *_pipe,
570 struct pipe_fence_handle **fence, unsigned flags)
571 {
572 struct dd_context *dctx = dd_context(_pipe);
573 struct pipe_context *pipe = dctx->pipe;
574
575 switch (dd_screen(dctx->base.screen)->mode) {
576 case DD_DETECT_HANGS:
577 dd_flush_and_handle_hang(dctx, fence, flags,
578 "GPU hang detected in pipe->flush()");
579 break;
580 case DD_DUMP_ALL_CALLS:
581 pipe->flush(pipe, fence, flags);
582 break;
583 default:
584 assert(0);
585 }
586 }
587
588 static void
589 dd_before_draw(struct dd_context *dctx)
590 {
591 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
592
593 if (dscreen->mode == DD_DETECT_HANGS &&
594 !dscreen->no_flush &&
595 dctx->num_draw_calls >= dscreen->skip_count)
596 dd_flush_and_handle_hang(dctx, NULL, 0,
597 "GPU hang most likely caused by internal "
598 "driver commands");
599 }
600
601 static void
602 dd_after_draw(struct dd_context *dctx, struct dd_call *call)
603 {
604 struct dd_screen *dscreen = dd_screen(dctx->base.screen);
605
606 if (dctx->num_draw_calls >= dscreen->skip_count) {
607 switch (dscreen->mode) {
608 case DD_DETECT_HANGS:
609 if (!dscreen->no_flush &&
610 dd_flush_and_check_hang(dctx, NULL, 0)) {
611 dd_dump_call(dctx, call, PIPE_DEBUG_DEVICE_IS_HUNG);
612
613 /* Terminate the process to prevent future hangs. */
614 dd_kill_process();
615 }
616 break;
617 case DD_DUMP_ALL_CALLS:
618 dd_dump_call(dctx, call, 0);
619 break;
620 default:
621 assert(0);
622 }
623 }
624
625 ++dctx->num_draw_calls;
626 }
627
628 static void
629 dd_context_draw_vbo(struct pipe_context *_pipe,
630 const struct pipe_draw_info *info)
631 {
632 struct dd_context *dctx = dd_context(_pipe);
633 struct pipe_context *pipe = dctx->pipe;
634 struct dd_call call;
635
636 call.type = CALL_DRAW_VBO;
637 call.info.draw_vbo = *info;
638
639 dd_before_draw(dctx);
640 pipe->draw_vbo(pipe, info);
641 dd_after_draw(dctx, &call);
642 }
643
644 static void
645 dd_context_resource_copy_region(struct pipe_context *_pipe,
646 struct pipe_resource *dst, unsigned dst_level,
647 unsigned dstx, unsigned dsty, unsigned dstz,
648 struct pipe_resource *src, unsigned src_level,
649 const struct pipe_box *src_box)
650 {
651 struct dd_context *dctx = dd_context(_pipe);
652 struct pipe_context *pipe = dctx->pipe;
653 struct dd_call call;
654
655 call.type = CALL_RESOURCE_COPY_REGION;
656 call.info.resource_copy_region.dst = dst;
657 call.info.resource_copy_region.dst_level = dst_level;
658 call.info.resource_copy_region.dstx = dstx;
659 call.info.resource_copy_region.dsty = dsty;
660 call.info.resource_copy_region.dstz = dstz;
661 call.info.resource_copy_region.src = src;
662 call.info.resource_copy_region.src_level = src_level;
663 call.info.resource_copy_region.src_box = src_box;
664
665 dd_before_draw(dctx);
666 pipe->resource_copy_region(pipe,
667 dst, dst_level, dstx, dsty, dstz,
668 src, src_level, src_box);
669 dd_after_draw(dctx, &call);
670 }
671
672 static void
673 dd_context_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
674 {
675 struct dd_context *dctx = dd_context(_pipe);
676 struct pipe_context *pipe = dctx->pipe;
677 struct dd_call call;
678
679 call.type = CALL_BLIT;
680 call.info.blit = *info;
681
682 dd_before_draw(dctx);
683 pipe->blit(pipe, info);
684 dd_after_draw(dctx, &call);
685 }
686
687 static void
688 dd_context_flush_resource(struct pipe_context *_pipe,
689 struct pipe_resource *resource)
690 {
691 struct dd_context *dctx = dd_context(_pipe);
692 struct pipe_context *pipe = dctx->pipe;
693 struct dd_call call;
694
695 call.type = CALL_FLUSH_RESOURCE;
696 call.info.flush_resource = resource;
697
698 dd_before_draw(dctx);
699 pipe->flush_resource(pipe, resource);
700 dd_after_draw(dctx, &call);
701 }
702
703 static void
704 dd_context_clear(struct pipe_context *_pipe, unsigned buffers,
705 const union pipe_color_union *color, double depth,
706 unsigned stencil)
707 {
708 struct dd_context *dctx = dd_context(_pipe);
709 struct pipe_context *pipe = dctx->pipe;
710 struct dd_call call;
711
712 call.type = CALL_CLEAR;
713 call.info.clear.buffers = buffers;
714 call.info.clear.color = color;
715 call.info.clear.depth = depth;
716 call.info.clear.stencil = stencil;
717
718 dd_before_draw(dctx);
719 pipe->clear(pipe, buffers, color, depth, stencil);
720 dd_after_draw(dctx, &call);
721 }
722
723 static void
724 dd_context_clear_render_target(struct pipe_context *_pipe,
725 struct pipe_surface *dst,
726 const union pipe_color_union *color,
727 unsigned dstx, unsigned dsty,
728 unsigned width, unsigned height)
729 {
730 struct dd_context *dctx = dd_context(_pipe);
731 struct pipe_context *pipe = dctx->pipe;
732 struct dd_call call;
733
734 call.type = CALL_CLEAR_RENDER_TARGET;
735
736 dd_before_draw(dctx);
737 pipe->clear_render_target(pipe, dst, color, dstx, dsty, width, height);
738 dd_after_draw(dctx, &call);
739 }
740
741 static void
742 dd_context_clear_depth_stencil(struct pipe_context *_pipe,
743 struct pipe_surface *dst, unsigned clear_flags,
744 double depth, unsigned stencil, unsigned dstx,
745 unsigned dsty, unsigned width, unsigned height)
746 {
747 struct dd_context *dctx = dd_context(_pipe);
748 struct pipe_context *pipe = dctx->pipe;
749 struct dd_call call;
750
751 call.type = CALL_CLEAR_DEPTH_STENCIL;
752
753 dd_before_draw(dctx);
754 pipe->clear_depth_stencil(pipe, dst, clear_flags, depth, stencil,
755 dstx, dsty, width, height);
756 dd_after_draw(dctx, &call);
757 }
758
759 static void
760 dd_context_clear_buffer(struct pipe_context *_pipe, struct pipe_resource *res,
761 unsigned offset, unsigned size,
762 const void *clear_value, int clear_value_size)
763 {
764 struct dd_context *dctx = dd_context(_pipe);
765 struct pipe_context *pipe = dctx->pipe;
766 struct dd_call call;
767
768 call.type = CALL_CLEAR_BUFFER;
769 call.info.clear_buffer.res = res;
770 call.info.clear_buffer.offset = offset;
771 call.info.clear_buffer.size = size;
772 call.info.clear_buffer.clear_value = clear_value;
773 call.info.clear_buffer.clear_value_size = clear_value_size;
774
775 dd_before_draw(dctx);
776 pipe->clear_buffer(pipe, res, offset, size, clear_value, clear_value_size);
777 dd_after_draw(dctx, &call);
778 }
779
780 void
781 dd_init_draw_functions(struct dd_context *dctx)
782 {
783 CTX_INIT(flush);
784 CTX_INIT(draw_vbo);
785 CTX_INIT(resource_copy_region);
786 CTX_INIT(blit);
787 CTX_INIT(clear);
788 CTX_INIT(clear_render_target);
789 CTX_INIT(clear_depth_stencil);
790 CTX_INIT(clear_buffer);
791 CTX_INIT(flush_resource);
792 /* launch_grid */
793 }