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