output.c revision 494e0025d995fb2cab04474d13880ee438b0c868
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 */
41VdpStatus
42vlVdpOutputSurfaceCreate(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 */
124VdpStatus
125vlVdpOutputSurfaceDestroy(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 */
148VdpStatus
149vlVdpOutputSurfaceGetParameters(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 */
170VdpStatus
171vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
172                                VdpRect const *source_rect,
173                                void *const *destination_data,
174                                uint32_t const *destination_pitches)
175{
176   return VDP_STATUS_NO_IMPLEMENTATION;
177}
178
179/**
180 * Copy image data from application memory in the surface's native format to
181 * a VdpOutputSurface.
182 */
183VdpStatus
184vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
185                                void const *const *source_data,
186                                uint32_t const *source_pitches,
187                                VdpRect const *destination_rect)
188{
189   vlVdpOutputSurface *vlsurface;
190   struct pipe_box dst_box;
191   struct pipe_context *pipe;
192
193   vlsurface = vlGetDataHTAB(surface);
194   if (!vlsurface)
195      return VDP_STATUS_INVALID_HANDLE;
196
197   pipe = vlsurface->device->context;
198   if (!pipe)
199      return VDP_STATUS_INVALID_HANDLE;
200
201   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
202
203   dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
204   pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
205                               PIPE_TRANSFER_WRITE, &dst_box, *source_data,
206                               *source_pitches, 0);
207
208   return VDP_STATUS_OK;
209}
210
211/**
212 * Copy image data from application memory in a specific indexed format to
213 * a VdpOutputSurface.
214 */
215VdpStatus
216vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
217                                 VdpIndexedFormat source_indexed_format,
218                                 void const *const *source_data,
219                                 uint32_t const *source_pitch,
220                                 VdpRect const *destination_rect,
221                                 VdpColorTableFormat color_table_format,
222                                 void const *color_table)
223{
224   vlVdpOutputSurface *vlsurface;
225   struct pipe_context *context;
226   struct vl_compositor *compositor;
227   struct vl_compositor_state *cstate;
228
229   enum pipe_format index_format;
230   enum pipe_format colortbl_format;
231
232   struct pipe_resource *res, res_tmpl;
233   struct pipe_sampler_view sv_tmpl;
234   struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
235
236   struct pipe_box box;
237   struct u_rect dst_rect;
238
239   vlsurface = vlGetDataHTAB(surface);
240   if (!vlsurface)
241      return VDP_STATUS_INVALID_HANDLE;
242
243   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
244
245   context = vlsurface->device->context;
246   compositor = &vlsurface->device->compositor;
247   cstate = &vlsurface->cstate;
248
249   index_format = FormatIndexedToPipe(source_indexed_format);
250   if (index_format == PIPE_FORMAT_NONE)
251       return VDP_STATUS_INVALID_INDEXED_FORMAT;
252
253   if (!source_data || !source_pitch)
254       return VDP_STATUS_INVALID_POINTER;
255
256   colortbl_format = FormatColorTableToPipe(color_table_format);
257   if (colortbl_format == PIPE_FORMAT_NONE)
258       return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
259
260   if (!color_table)
261       return VDP_STATUS_INVALID_POINTER;
262
263   memset(&res_tmpl, 0, sizeof(res_tmpl));
264   res_tmpl.target = PIPE_TEXTURE_2D;
265   res_tmpl.format = index_format;
266
267   if (destination_rect) {
268      res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
269      res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
270   } else {
271      res_tmpl.width0 = vlsurface->surface->texture->width0;
272      res_tmpl.height0 = vlsurface->surface->texture->height0;
273   }
274   res_tmpl.depth0 = 1;
275   res_tmpl.array_size = 1;
276   res_tmpl.usage = PIPE_USAGE_STAGING;
277   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
278
279   res = context->screen->resource_create(context->screen, &res_tmpl);
280   if (!res)
281      goto error_resource;
282
283   box.x = box.y = box.z = 0;
284   box.width = res->width0;
285   box.height = res->height0;
286   box.depth = res->depth0;
287
288   context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
289                                  source_data[0], source_pitch[0],
290                                  source_pitch[0] * res->height0);
291
292   memset(&sv_tmpl, 0, sizeof(sv_tmpl));
293   u_sampler_view_default_template(&sv_tmpl, res, res->format);
294
295   sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
296   pipe_resource_reference(&res, NULL);
297
298   if (!sv_idx)
299      goto error_resource;
300
301   memset(&res_tmpl, 0, sizeof(res_tmpl));
302   res_tmpl.target = PIPE_TEXTURE_1D;
303   res_tmpl.format = colortbl_format;
304   res_tmpl.width0 = 1 << util_format_get_component_bits(
305      index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
306   res_tmpl.height0 = 1;
307   res_tmpl.depth0 = 1;
308   res_tmpl.array_size = 1;
309   res_tmpl.usage = PIPE_USAGE_STAGING;
310   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
311
312   res = context->screen->resource_create(context->screen, &res_tmpl);
313   if (!res)
314      goto error_resource;
315
316   box.x = box.y = box.z = 0;
317   box.width = res->width0;
318   box.height = res->height0;
319   box.depth = res->depth0;
320
321   context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
322                                  util_format_get_stride(colortbl_format, res->width0), 0);
323
324   memset(&sv_tmpl, 0, sizeof(sv_tmpl));
325   u_sampler_view_default_template(&sv_tmpl, res, res->format);
326
327   sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
328   pipe_resource_reference(&res, NULL);
329
330   if (!sv_tbl)
331      goto error_resource;
332
333   vl_compositor_clear_layers(cstate);
334   vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
335   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
336   vl_compositor_render(cstate, compositor, vlsurface->surface, NULL);
337
338   pipe_sampler_view_reference(&sv_idx, NULL);
339   pipe_sampler_view_reference(&sv_tbl, NULL);
340
341   return VDP_STATUS_OK;
342
343error_resource:
344   pipe_sampler_view_reference(&sv_idx, NULL);
345   pipe_sampler_view_reference(&sv_tbl, NULL);
346   return VDP_STATUS_RESOURCES;
347}
348
349/**
350 * Copy image data from application memory in a specific YCbCr format to
351 * a VdpOutputSurface.
352 */
353VdpStatus
354vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
355                               VdpYCbCrFormat source_ycbcr_format,
356                               void const *const *source_data,
357                               uint32_t const *source_pitches,
358                               VdpRect const *destination_rect,
359                               VdpCSCMatrix const *csc_matrix)
360{
361   return VDP_STATUS_NO_IMPLEMENTATION;
362}
363
364static unsigned
365BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
366{
367   switch (factor) {
368   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
369      return PIPE_BLENDFACTOR_ZERO;
370   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
371      return PIPE_BLENDFACTOR_ONE;
372   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
373      return PIPE_BLENDFACTOR_SRC_COLOR;
374   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
375      return PIPE_BLENDFACTOR_INV_SRC_COLOR;
376   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
377      return PIPE_BLENDFACTOR_SRC_ALPHA;
378   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
379      return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
380   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
381      return PIPE_BLENDFACTOR_DST_ALPHA;
382   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
383      return PIPE_BLENDFACTOR_INV_DST_ALPHA;
384   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
385      return PIPE_BLENDFACTOR_DST_COLOR;
386   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
387      return PIPE_BLENDFACTOR_INV_DST_COLOR;
388   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
389      return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
390   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
391      return PIPE_BLENDFACTOR_CONST_COLOR;
392   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
393      return PIPE_BLENDFACTOR_INV_CONST_COLOR;
394   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
395      return PIPE_BLENDFACTOR_CONST_ALPHA;
396   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
397      return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
398   default:
399      assert(0);
400      return PIPE_BLENDFACTOR_ONE;
401   }
402}
403
404static unsigned
405BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
406{
407   switch (equation) {
408   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
409      return PIPE_BLEND_SUBTRACT;
410   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
411      return PIPE_BLEND_REVERSE_SUBTRACT;
412   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
413      return PIPE_BLEND_ADD;
414   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
415      return PIPE_BLEND_MIN;
416   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
417      return PIPE_BLEND_MAX;
418   default:
419      assert(0);
420      return PIPE_BLEND_ADD;
421   }
422}
423
424static void *
425BlenderToPipe(struct pipe_context *context,
426              VdpOutputSurfaceRenderBlendState const *blend_state)
427{
428   struct pipe_blend_state blend;
429
430   memset(&blend, 0, sizeof blend);
431   blend.independent_blend_enable = 0;
432
433   if (blend_state) {
434      blend.rt[0].blend_enable = 1;
435      blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
436      blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
437      blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
438      blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
439      blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
440      blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
441   } else {
442      blend.rt[0].blend_enable = 0;
443   }
444
445   blend.logicop_enable = 0;
446   blend.logicop_func = PIPE_LOGICOP_CLEAR;
447   blend.rt[0].colormask = PIPE_MASK_RGBA;
448   blend.dither = 0;
449
450   return context->create_blend_state(context, &blend);
451}
452
453static struct vertex4f *
454ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
455{
456   unsigned i;
457   struct vertex4f *dst = result;
458
459   if (!colors)
460      return NULL;
461
462   for (i = 0; i < 4; ++i) {
463      dst->x = colors->red;
464      dst->y = colors->green;
465      dst->z = colors->blue;
466      dst->w = colors->alpha;
467
468      ++dst;
469      if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
470         ++colors;
471   }
472   return result;
473}
474
475/**
476 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
477 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
478 */
479VdpStatus
480vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
481                                      VdpRect const *destination_rect,
482                                      VdpOutputSurface source_surface,
483                                      VdpRect const *source_rect,
484                                      VdpColor const *colors,
485                                      VdpOutputSurfaceRenderBlendState const *blend_state,
486                                      uint32_t flags)
487{
488   vlVdpOutputSurface *dst_vlsurface;
489   vlVdpOutputSurface *src_vlsurface;
490
491   struct pipe_context *context;
492   struct vl_compositor *compositor;
493   struct vl_compositor_state *cstate;
494
495   struct u_rect src_rect, dst_rect;
496
497   struct vertex4f vlcolors[4];
498   void *blend;
499
500   dst_vlsurface = vlGetDataHTAB(destination_surface);
501   if (!dst_vlsurface)
502      return VDP_STATUS_INVALID_HANDLE;
503
504   src_vlsurface = vlGetDataHTAB(source_surface);
505   if (!src_vlsurface)
506      return VDP_STATUS_INVALID_HANDLE;
507
508   if (dst_vlsurface->device != src_vlsurface->device)
509      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
510
511   vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
512
513   context = dst_vlsurface->device->context;
514   compositor = &dst_vlsurface->device->compositor;
515   cstate = &dst_vlsurface->cstate;
516
517   blend = BlenderToPipe(context, blend_state);
518
519   vl_compositor_clear_layers(cstate);
520   vl_compositor_set_layer_blend(cstate, 0, blend, false);
521   vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
522                                RectToPipe(source_rect, &src_rect), NULL,
523                                ColorsToPipe(colors, flags, vlcolors));
524   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
525   vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
526
527   context->delete_blend_state(context, blend);
528
529   return VDP_STATUS_OK;
530}
531
532/**
533 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
534 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
535 */
536VdpStatus
537vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
538                                      VdpRect const *destination_rect,
539                                      VdpBitmapSurface source_surface,
540                                      VdpRect const *source_rect,
541                                      VdpColor const *colors,
542                                      VdpOutputSurfaceRenderBlendState const *blend_state,
543                                      uint32_t flags)
544{
545   vlVdpOutputSurface *dst_vlsurface;
546   vlVdpBitmapSurface *src_vlsurface;
547
548   struct pipe_context *context;
549   struct vl_compositor *compositor;
550   struct vl_compositor_state *cstate;
551
552   struct u_rect src_rect, dst_rect;
553
554   struct vertex4f vlcolors[4];
555   void *blend;
556
557   dst_vlsurface = vlGetDataHTAB(destination_surface);
558   if (!dst_vlsurface)
559      return VDP_STATUS_INVALID_HANDLE;
560
561   src_vlsurface = vlGetDataHTAB(source_surface);
562   if (!src_vlsurface)
563      return VDP_STATUS_INVALID_HANDLE;
564
565   if (dst_vlsurface->device != src_vlsurface->device)
566      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
567
568   vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
569
570   context = dst_vlsurface->device->context;
571   compositor = &dst_vlsurface->device->compositor;
572   cstate = &dst_vlsurface->cstate;
573
574   blend = BlenderToPipe(context, blend_state);
575
576   vl_compositor_clear_layers(cstate);
577   vl_compositor_set_layer_blend(cstate, 0, blend, false);
578   vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
579                                RectToPipe(source_rect, &src_rect), NULL,
580                                ColorsToPipe(colors, flags, vlcolors));
581   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
582   vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
583
584   context->delete_blend_state(context, blend);
585
586   return VDP_STATUS_OK;
587}
588