56ce315db7f44e891e781e67d65522bd26427f56
[mesa.git] / src / gallium / state_trackers / vdpau / output.c
1 /**************************************************************************
2 *
3 * Copyright 2010 Thomas Balling Sørensen.
4 * Copyright 2011 Christian König.
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
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sub license, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *
27 **************************************************************************/
28
29 #include <vdpau/vdpau.h>
30
31 #include "util/u_debug.h"
32 #include "util/u_memory.h"
33 #include "util/u_sampler.h"
34 #include "util/u_format.h"
35
36 #include "vdpau_private.h"
37
38 /**
39 * Create a VdpOutputSurface.
40 */
41 VdpStatus
42 vlVdpOutputSurfaceCreate(VdpDevice device,
43 VdpRGBAFormat rgba_format,
44 uint32_t width, uint32_t height,
45 VdpOutputSurface *surface)
46 {
47 struct pipe_context *pipe;
48 struct pipe_resource res_tmpl, *res;
49 struct pipe_sampler_view sv_templ;
50 struct pipe_surface surf_templ;
51
52 vlVdpOutputSurface *vlsurface = NULL;
53
54 if (!(width && height))
55 return VDP_STATUS_INVALID_SIZE;
56
57 vlVdpDevice *dev = vlGetDataHTAB(device);
58 if (!dev)
59 return VDP_STATUS_INVALID_HANDLE;
60
61 pipe = dev->context;
62 if (!pipe)
63 return VDP_STATUS_INVALID_HANDLE;
64
65 vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface));
66 if (!vlsurface)
67 return VDP_STATUS_RESOURCES;
68
69 vlsurface->device = dev;
70
71 memset(&res_tmpl, 0, sizeof(res_tmpl));
72
73 res_tmpl.target = PIPE_TEXTURE_2D;
74 res_tmpl.format = FormatRGBAToPipe(rgba_format);
75 res_tmpl.width0 = width;
76 res_tmpl.height0 = height;
77 res_tmpl.depth0 = 1;
78 res_tmpl.array_size = 1;
79 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
80 res_tmpl.usage = PIPE_USAGE_STATIC;
81
82 res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
83 if (!res) {
84 FREE(dev);
85 return VDP_STATUS_ERROR;
86 }
87
88 vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
89 vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
90 if (!vlsurface->sampler_view) {
91 pipe_resource_reference(&res, NULL);
92 FREE(dev);
93 return VDP_STATUS_ERROR;
94 }
95
96 memset(&surf_templ, 0, sizeof(surf_templ));
97 surf_templ.format = res->format;
98 surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
99 vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
100 if (!vlsurface->surface) {
101 pipe_resource_reference(&res, NULL);
102 FREE(dev);
103 return VDP_STATUS_ERROR;
104 }
105
106 *surface = vlAddDataHTAB(vlsurface);
107 if (*surface == 0) {
108 pipe_resource_reference(&res, NULL);
109 FREE(dev);
110 return VDP_STATUS_ERROR;
111 }
112
113 pipe_resource_reference(&res, NULL);
114
115 vl_compositor_init_state(&vlsurface->cstate, pipe);
116 vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
117
118 return VDP_STATUS_OK;
119 }
120
121 /**
122 * Destroy a VdpOutputSurface.
123 */
124 VdpStatus
125 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
126 {
127 vlVdpOutputSurface *vlsurface;
128
129 vlsurface = vlGetDataHTAB(surface);
130 if (!vlsurface)
131 return VDP_STATUS_INVALID_HANDLE;
132
133 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
134
135 pipe_surface_reference(&vlsurface->surface, NULL);
136 pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
137 vl_compositor_cleanup_state(&vlsurface->cstate);
138
139 vlRemoveDataHTAB(surface);
140 FREE(vlsurface);
141
142 return VDP_STATUS_OK;
143 }
144
145 /**
146 * Retrieve the parameters used to create a VdpOutputSurface.
147 */
148 VdpStatus
149 vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
150 VdpRGBAFormat *rgba_format,
151 uint32_t *width, uint32_t *height)
152 {
153 vlVdpOutputSurface *vlsurface;
154
155 vlsurface = vlGetDataHTAB(surface);
156 if (!vlsurface)
157 return VDP_STATUS_INVALID_HANDLE;
158
159 *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
160 *width = vlsurface->sampler_view->texture->width0;
161 *height = vlsurface->sampler_view->texture->height0;
162
163 return VDP_STATUS_OK;
164 }
165
166 /**
167 * Copy image data from a VdpOutputSurface to application memory in the
168 * surface's native format.
169 */
170 VdpStatus
171 vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
172 VdpRect const *source_rect,
173 void *const *destination_data,
174 uint32_t const *destination_pitches)
175 {
176 vlVdpOutputSurface *vlsurface;
177 struct pipe_context *pipe;
178 struct pipe_resource *res;
179 struct pipe_box box;
180 struct pipe_transfer *transfer;
181 uint8_t *map;
182
183 vlsurface = vlGetDataHTAB(surface);
184 if (!vlsurface)
185 return VDP_STATUS_INVALID_HANDLE;
186
187 pipe = vlsurface->device->context;
188 if (!pipe)
189 return VDP_STATUS_INVALID_HANDLE;
190
191 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
192
193 res = vlsurface->sampler_view->texture;
194 box = RectToPipeBox(source_rect, res);
195 transfer = pipe->get_transfer(pipe, res, 0, PIPE_TRANSFER_READ, &box);
196 if (transfer == NULL)
197 return VDP_STATUS_RESOURCES;
198
199 map = pipe_transfer_map(pipe, transfer);
200 if (map == NULL) {
201 pipe_transfer_destroy(pipe, transfer);
202 return VDP_STATUS_RESOURCES;
203 }
204
205 util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
206 box.width, box.height, map, transfer->stride, 0, 0);
207
208 pipe_transfer_unmap(pipe, transfer);
209 pipe_transfer_destroy(pipe, transfer);
210
211 return VDP_STATUS_OK;
212 }
213
214 /**
215 * Copy image data from application memory in the surface's native format to
216 * a VdpOutputSurface.
217 */
218 VdpStatus
219 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
220 void const *const *source_data,
221 uint32_t const *source_pitches,
222 VdpRect const *destination_rect)
223 {
224 vlVdpOutputSurface *vlsurface;
225 struct pipe_box dst_box;
226 struct pipe_context *pipe;
227
228 vlsurface = vlGetDataHTAB(surface);
229 if (!vlsurface)
230 return VDP_STATUS_INVALID_HANDLE;
231
232 pipe = vlsurface->device->context;
233 if (!pipe)
234 return VDP_STATUS_INVALID_HANDLE;
235
236 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
237
238 dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
239 pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
240 PIPE_TRANSFER_WRITE, &dst_box, *source_data,
241 *source_pitches, 0);
242
243 return VDP_STATUS_OK;
244 }
245
246 /**
247 * Copy image data from application memory in a specific indexed format to
248 * a VdpOutputSurface.
249 */
250 VdpStatus
251 vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
252 VdpIndexedFormat source_indexed_format,
253 void const *const *source_data,
254 uint32_t const *source_pitch,
255 VdpRect const *destination_rect,
256 VdpColorTableFormat color_table_format,
257 void const *color_table)
258 {
259 vlVdpOutputSurface *vlsurface;
260 struct pipe_context *context;
261 struct vl_compositor *compositor;
262 struct vl_compositor_state *cstate;
263
264 enum pipe_format index_format;
265 enum pipe_format colortbl_format;
266
267 struct pipe_resource *res, res_tmpl;
268 struct pipe_sampler_view sv_tmpl;
269 struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
270
271 struct pipe_box box;
272 struct u_rect dst_rect;
273
274 vlsurface = vlGetDataHTAB(surface);
275 if (!vlsurface)
276 return VDP_STATUS_INVALID_HANDLE;
277
278 vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
279
280 context = vlsurface->device->context;
281 compositor = &vlsurface->device->compositor;
282 cstate = &vlsurface->cstate;
283
284 index_format = FormatIndexedToPipe(source_indexed_format);
285 if (index_format == PIPE_FORMAT_NONE)
286 return VDP_STATUS_INVALID_INDEXED_FORMAT;
287
288 if (!source_data || !source_pitch)
289 return VDP_STATUS_INVALID_POINTER;
290
291 colortbl_format = FormatColorTableToPipe(color_table_format);
292 if (colortbl_format == PIPE_FORMAT_NONE)
293 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
294
295 if (!color_table)
296 return VDP_STATUS_INVALID_POINTER;
297
298 memset(&res_tmpl, 0, sizeof(res_tmpl));
299 res_tmpl.target = PIPE_TEXTURE_2D;
300 res_tmpl.format = index_format;
301
302 if (destination_rect) {
303 res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
304 res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
305 } else {
306 res_tmpl.width0 = vlsurface->surface->texture->width0;
307 res_tmpl.height0 = vlsurface->surface->texture->height0;
308 }
309 res_tmpl.depth0 = 1;
310 res_tmpl.array_size = 1;
311 res_tmpl.usage = PIPE_USAGE_STAGING;
312 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
313
314 res = context->screen->resource_create(context->screen, &res_tmpl);
315 if (!res)
316 goto error_resource;
317
318 box.x = box.y = box.z = 0;
319 box.width = res->width0;
320 box.height = res->height0;
321 box.depth = res->depth0;
322
323 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
324 source_data[0], source_pitch[0],
325 source_pitch[0] * res->height0);
326
327 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
328 u_sampler_view_default_template(&sv_tmpl, res, res->format);
329
330 sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
331 pipe_resource_reference(&res, NULL);
332
333 if (!sv_idx)
334 goto error_resource;
335
336 memset(&res_tmpl, 0, sizeof(res_tmpl));
337 res_tmpl.target = PIPE_TEXTURE_1D;
338 res_tmpl.format = colortbl_format;
339 res_tmpl.width0 = 1 << util_format_get_component_bits(
340 index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
341 res_tmpl.height0 = 1;
342 res_tmpl.depth0 = 1;
343 res_tmpl.array_size = 1;
344 res_tmpl.usage = PIPE_USAGE_STAGING;
345 res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
346
347 res = context->screen->resource_create(context->screen, &res_tmpl);
348 if (!res)
349 goto error_resource;
350
351 box.x = box.y = box.z = 0;
352 box.width = res->width0;
353 box.height = res->height0;
354 box.depth = res->depth0;
355
356 context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
357 util_format_get_stride(colortbl_format, res->width0), 0);
358
359 memset(&sv_tmpl, 0, sizeof(sv_tmpl));
360 u_sampler_view_default_template(&sv_tmpl, res, res->format);
361
362 sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
363 pipe_resource_reference(&res, NULL);
364
365 if (!sv_tbl)
366 goto error_resource;
367
368 vl_compositor_clear_layers(cstate);
369 vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
370 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
371 vl_compositor_render(cstate, compositor, vlsurface->surface, NULL);
372
373 pipe_sampler_view_reference(&sv_idx, NULL);
374 pipe_sampler_view_reference(&sv_tbl, NULL);
375
376 return VDP_STATUS_OK;
377
378 error_resource:
379 pipe_sampler_view_reference(&sv_idx, NULL);
380 pipe_sampler_view_reference(&sv_tbl, NULL);
381 return VDP_STATUS_RESOURCES;
382 }
383
384 /**
385 * Copy image data from application memory in a specific YCbCr format to
386 * a VdpOutputSurface.
387 */
388 VdpStatus
389 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
390 VdpYCbCrFormat source_ycbcr_format,
391 void const *const *source_data,
392 uint32_t const *source_pitches,
393 VdpRect const *destination_rect,
394 VdpCSCMatrix const *csc_matrix)
395 {
396 return VDP_STATUS_NO_IMPLEMENTATION;
397 }
398
399 static unsigned
400 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
401 {
402 switch (factor) {
403 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
404 return PIPE_BLENDFACTOR_ZERO;
405 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
406 return PIPE_BLENDFACTOR_ONE;
407 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
408 return PIPE_BLENDFACTOR_SRC_COLOR;
409 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
410 return PIPE_BLENDFACTOR_INV_SRC_COLOR;
411 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
412 return PIPE_BLENDFACTOR_SRC_ALPHA;
413 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
414 return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
415 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
416 return PIPE_BLENDFACTOR_DST_ALPHA;
417 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
418 return PIPE_BLENDFACTOR_INV_DST_ALPHA;
419 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
420 return PIPE_BLENDFACTOR_DST_COLOR;
421 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
422 return PIPE_BLENDFACTOR_INV_DST_COLOR;
423 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
424 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
425 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
426 return PIPE_BLENDFACTOR_CONST_COLOR;
427 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
428 return PIPE_BLENDFACTOR_INV_CONST_COLOR;
429 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
430 return PIPE_BLENDFACTOR_CONST_ALPHA;
431 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
432 return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
433 default:
434 assert(0);
435 return PIPE_BLENDFACTOR_ONE;
436 }
437 }
438
439 static unsigned
440 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
441 {
442 switch (equation) {
443 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
444 return PIPE_BLEND_SUBTRACT;
445 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
446 return PIPE_BLEND_REVERSE_SUBTRACT;
447 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
448 return PIPE_BLEND_ADD;
449 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
450 return PIPE_BLEND_MIN;
451 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
452 return PIPE_BLEND_MAX;
453 default:
454 assert(0);
455 return PIPE_BLEND_ADD;
456 }
457 }
458
459 static void *
460 BlenderToPipe(struct pipe_context *context,
461 VdpOutputSurfaceRenderBlendState const *blend_state)
462 {
463 struct pipe_blend_state blend;
464
465 memset(&blend, 0, sizeof blend);
466 blend.independent_blend_enable = 0;
467
468 if (blend_state) {
469 blend.rt[0].blend_enable = 1;
470 blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
471 blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
472 blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
473 blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
474 blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
475 blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
476 } else {
477 blend.rt[0].blend_enable = 0;
478 }
479
480 blend.logicop_enable = 0;
481 blend.logicop_func = PIPE_LOGICOP_CLEAR;
482 blend.rt[0].colormask = PIPE_MASK_RGBA;
483 blend.dither = 0;
484
485 return context->create_blend_state(context, &blend);
486 }
487
488 static struct vertex4f *
489 ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
490 {
491 unsigned i;
492 struct vertex4f *dst = result;
493
494 if (!colors)
495 return NULL;
496
497 for (i = 0; i < 4; ++i) {
498 dst->x = colors->red;
499 dst->y = colors->green;
500 dst->z = colors->blue;
501 dst->w = colors->alpha;
502
503 ++dst;
504 if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
505 ++colors;
506 }
507 return result;
508 }
509
510 /**
511 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
512 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
513 */
514 VdpStatus
515 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
516 VdpRect const *destination_rect,
517 VdpOutputSurface source_surface,
518 VdpRect const *source_rect,
519 VdpColor const *colors,
520 VdpOutputSurfaceRenderBlendState const *blend_state,
521 uint32_t flags)
522 {
523 vlVdpOutputSurface *dst_vlsurface;
524 vlVdpOutputSurface *src_vlsurface;
525
526 struct pipe_context *context;
527 struct vl_compositor *compositor;
528 struct vl_compositor_state *cstate;
529
530 struct u_rect src_rect, dst_rect;
531
532 struct vertex4f vlcolors[4];
533 void *blend;
534
535 dst_vlsurface = vlGetDataHTAB(destination_surface);
536 if (!dst_vlsurface)
537 return VDP_STATUS_INVALID_HANDLE;
538
539 src_vlsurface = vlGetDataHTAB(source_surface);
540 if (!src_vlsurface)
541 return VDP_STATUS_INVALID_HANDLE;
542
543 if (dst_vlsurface->device != src_vlsurface->device)
544 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
545
546 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
547
548 context = dst_vlsurface->device->context;
549 compositor = &dst_vlsurface->device->compositor;
550 cstate = &dst_vlsurface->cstate;
551
552 blend = BlenderToPipe(context, blend_state);
553
554 vl_compositor_clear_layers(cstate);
555 vl_compositor_set_layer_blend(cstate, 0, blend, false);
556 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
557 RectToPipe(source_rect, &src_rect), NULL,
558 ColorsToPipe(colors, flags, vlcolors));
559 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
560 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
561
562 context->delete_blend_state(context, blend);
563
564 return VDP_STATUS_OK;
565 }
566
567 /**
568 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
569 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
570 */
571 VdpStatus
572 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
573 VdpRect const *destination_rect,
574 VdpBitmapSurface source_surface,
575 VdpRect const *source_rect,
576 VdpColor const *colors,
577 VdpOutputSurfaceRenderBlendState const *blend_state,
578 uint32_t flags)
579 {
580 vlVdpOutputSurface *dst_vlsurface;
581 vlVdpBitmapSurface *src_vlsurface;
582
583 struct pipe_context *context;
584 struct vl_compositor *compositor;
585 struct vl_compositor_state *cstate;
586
587 struct u_rect src_rect, dst_rect;
588
589 struct vertex4f vlcolors[4];
590 void *blend;
591
592 dst_vlsurface = vlGetDataHTAB(destination_surface);
593 if (!dst_vlsurface)
594 return VDP_STATUS_INVALID_HANDLE;
595
596 src_vlsurface = vlGetDataHTAB(source_surface);
597 if (!src_vlsurface)
598 return VDP_STATUS_INVALID_HANDLE;
599
600 if (dst_vlsurface->device != src_vlsurface->device)
601 return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
602
603 vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
604
605 context = dst_vlsurface->device->context;
606 compositor = &dst_vlsurface->device->compositor;
607 cstate = &dst_vlsurface->cstate;
608
609 blend = BlenderToPipe(context, blend_state);
610
611 vl_compositor_clear_layers(cstate);
612 vl_compositor_set_layer_blend(cstate, 0, blend, false);
613 vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
614 RectToPipe(source_rect, &src_rect), NULL,
615 ColorsToPipe(colors, flags, vlcolors));
616 vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
617 vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
618
619 context->delete_blend_state(context, blend);
620
621 return VDP_STATUS_OK;
622 }