output.c revision d14c879d82d62f4000045dc6f001186559b81faa
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 "vl/vl_csc.h"
37
38#include "vdpau_private.h"
39
40/**
41 * Create a VdpOutputSurface.
42 */
43VdpStatus
44vlVdpOutputSurfaceCreate(VdpDevice device,
45                         VdpRGBAFormat rgba_format,
46                         uint32_t width, uint32_t height,
47                         VdpOutputSurface  *surface)
48{
49   struct pipe_context *pipe;
50   struct pipe_resource res_tmpl, *res;
51   struct pipe_sampler_view sv_templ;
52   struct pipe_surface surf_templ;
53
54   vlVdpOutputSurface *vlsurface = NULL;
55
56   if (!(width && height))
57      return VDP_STATUS_INVALID_SIZE;
58
59   vlVdpDevice *dev = vlGetDataHTAB(device);
60   if (!dev)
61      return VDP_STATUS_INVALID_HANDLE;
62
63   pipe = dev->context;
64   if (!pipe)
65      return VDP_STATUS_INVALID_HANDLE;
66
67   vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface));
68   if (!vlsurface)
69      return VDP_STATUS_RESOURCES;
70
71   vlsurface->device = dev;
72
73   memset(&res_tmpl, 0, sizeof(res_tmpl));
74
75   res_tmpl.target = PIPE_TEXTURE_2D;
76   res_tmpl.format = FormatRGBAToPipe(rgba_format);
77   res_tmpl.width0 = width;
78   res_tmpl.height0 = height;
79   res_tmpl.depth0 = 1;
80   res_tmpl.array_size = 1;
81   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
82   res_tmpl.usage = PIPE_USAGE_STATIC;
83
84   res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
85   if (!res) {
86      FREE(dev);
87      return VDP_STATUS_ERROR;
88   }
89
90   vlVdpDefaultSamplerViewTemplate(&sv_templ, res);
91   vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
92   if (!vlsurface->sampler_view) {
93      pipe_resource_reference(&res, NULL);
94      FREE(dev);
95      return VDP_STATUS_ERROR;
96   }
97
98   memset(&surf_templ, 0, sizeof(surf_templ));
99   surf_templ.format = res->format;
100   surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
101   vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
102   if (!vlsurface->surface) {
103      pipe_resource_reference(&res, NULL);
104      FREE(dev);
105      return VDP_STATUS_ERROR;
106   }
107
108   *surface = vlAddDataHTAB(vlsurface);
109   if (*surface == 0) {
110      pipe_resource_reference(&res, NULL);
111      FREE(dev);
112      return VDP_STATUS_ERROR;
113   }
114
115   pipe_resource_reference(&res, NULL);
116
117   vl_compositor_init_state(&vlsurface->cstate, pipe);
118   vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
119
120   return VDP_STATUS_OK;
121}
122
123/**
124 * Destroy a VdpOutputSurface.
125 */
126VdpStatus
127vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
128{
129   vlVdpOutputSurface *vlsurface;
130
131   vlsurface = vlGetDataHTAB(surface);
132   if (!vlsurface)
133      return VDP_STATUS_INVALID_HANDLE;
134
135   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
136
137   pipe_surface_reference(&vlsurface->surface, NULL);
138   pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
139   vl_compositor_cleanup_state(&vlsurface->cstate);
140
141   vlRemoveDataHTAB(surface);
142   FREE(vlsurface);
143
144   return VDP_STATUS_OK;
145}
146
147/**
148 * Retrieve the parameters used to create a VdpOutputSurface.
149 */
150VdpStatus
151vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
152                                VdpRGBAFormat *rgba_format,
153                                uint32_t *width, uint32_t *height)
154{
155   vlVdpOutputSurface *vlsurface;
156
157   vlsurface = vlGetDataHTAB(surface);
158   if (!vlsurface)
159      return VDP_STATUS_INVALID_HANDLE;
160
161   *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
162   *width = vlsurface->sampler_view->texture->width0;
163   *height = vlsurface->sampler_view->texture->height0;
164
165   return VDP_STATUS_OK;
166}
167
168/**
169 * Copy image data from a VdpOutputSurface to application memory in the
170 * surface's native format.
171 */
172VdpStatus
173vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
174                                VdpRect const *source_rect,
175                                void *const *destination_data,
176                                uint32_t const *destination_pitches)
177{
178   vlVdpOutputSurface *vlsurface;
179   struct pipe_context *pipe;
180   struct pipe_resource *res;
181   struct pipe_box box;
182   struct pipe_transfer *transfer;
183   uint8_t *map;
184
185   vlsurface = vlGetDataHTAB(surface);
186   if (!vlsurface)
187      return VDP_STATUS_INVALID_HANDLE;
188
189   pipe = vlsurface->device->context;
190   if (!pipe)
191      return VDP_STATUS_INVALID_HANDLE;
192
193   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
194
195   res = vlsurface->sampler_view->texture;
196   box = RectToPipeBox(source_rect, res);
197   transfer = pipe->get_transfer(pipe, res, 0, PIPE_TRANSFER_READ, &box);
198   if (transfer == NULL)
199      return VDP_STATUS_RESOURCES;
200
201   map = pipe_transfer_map(pipe, transfer);
202   if (map == NULL) {
203      pipe_transfer_destroy(pipe, transfer);
204      return VDP_STATUS_RESOURCES;
205   }
206
207   util_copy_rect(*destination_data, res->format, *destination_pitches, 0, 0,
208                  box.width, box.height, map, transfer->stride, 0, 0);
209
210   pipe_transfer_unmap(pipe, transfer);
211   pipe_transfer_destroy(pipe, transfer);
212
213   return VDP_STATUS_OK;
214}
215
216/**
217 * Copy image data from application memory in the surface's native format to
218 * a VdpOutputSurface.
219 */
220VdpStatus
221vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
222                                void const *const *source_data,
223                                uint32_t const *source_pitches,
224                                VdpRect const *destination_rect)
225{
226   vlVdpOutputSurface *vlsurface;
227   struct pipe_box dst_box;
228   struct pipe_context *pipe;
229
230   vlsurface = vlGetDataHTAB(surface);
231   if (!vlsurface)
232      return VDP_STATUS_INVALID_HANDLE;
233
234   pipe = vlsurface->device->context;
235   if (!pipe)
236      return VDP_STATUS_INVALID_HANDLE;
237
238   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
239
240   dst_box = RectToPipeBox(destination_rect, vlsurface->sampler_view->texture);
241   pipe->transfer_inline_write(pipe, vlsurface->sampler_view->texture, 0,
242                               PIPE_TRANSFER_WRITE, &dst_box, *source_data,
243                               *source_pitches, 0);
244
245   return VDP_STATUS_OK;
246}
247
248/**
249 * Copy image data from application memory in a specific indexed format to
250 * a VdpOutputSurface.
251 */
252VdpStatus
253vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
254                                 VdpIndexedFormat source_indexed_format,
255                                 void const *const *source_data,
256                                 uint32_t const *source_pitch,
257                                 VdpRect const *destination_rect,
258                                 VdpColorTableFormat color_table_format,
259                                 void const *color_table)
260{
261   vlVdpOutputSurface *vlsurface;
262   struct pipe_context *context;
263   struct vl_compositor *compositor;
264   struct vl_compositor_state *cstate;
265
266   enum pipe_format index_format;
267   enum pipe_format colortbl_format;
268
269   struct pipe_resource *res, res_tmpl;
270   struct pipe_sampler_view sv_tmpl;
271   struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
272
273   struct pipe_box box;
274   struct u_rect dst_rect;
275
276   vlsurface = vlGetDataHTAB(surface);
277   if (!vlsurface)
278      return VDP_STATUS_INVALID_HANDLE;
279
280   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
281
282   context = vlsurface->device->context;
283   compositor = &vlsurface->device->compositor;
284   cstate = &vlsurface->cstate;
285
286   index_format = FormatIndexedToPipe(source_indexed_format);
287   if (index_format == PIPE_FORMAT_NONE)
288       return VDP_STATUS_INVALID_INDEXED_FORMAT;
289
290   if (!source_data || !source_pitch)
291       return VDP_STATUS_INVALID_POINTER;
292
293   colortbl_format = FormatColorTableToPipe(color_table_format);
294   if (colortbl_format == PIPE_FORMAT_NONE)
295       return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
296
297   if (!color_table)
298       return VDP_STATUS_INVALID_POINTER;
299
300   memset(&res_tmpl, 0, sizeof(res_tmpl));
301   res_tmpl.target = PIPE_TEXTURE_2D;
302   res_tmpl.format = index_format;
303
304   if (destination_rect) {
305      res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
306      res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
307   } else {
308      res_tmpl.width0 = vlsurface->surface->texture->width0;
309      res_tmpl.height0 = vlsurface->surface->texture->height0;
310   }
311   res_tmpl.depth0 = 1;
312   res_tmpl.array_size = 1;
313   res_tmpl.usage = PIPE_USAGE_STAGING;
314   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
315
316   res = context->screen->resource_create(context->screen, &res_tmpl);
317   if (!res)
318      goto error_resource;
319
320   box.x = box.y = box.z = 0;
321   box.width = res->width0;
322   box.height = res->height0;
323   box.depth = res->depth0;
324
325   context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
326                                  source_data[0], source_pitch[0],
327                                  source_pitch[0] * res->height0);
328
329   memset(&sv_tmpl, 0, sizeof(sv_tmpl));
330   u_sampler_view_default_template(&sv_tmpl, res, res->format);
331
332   sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
333   pipe_resource_reference(&res, NULL);
334
335   if (!sv_idx)
336      goto error_resource;
337
338   memset(&res_tmpl, 0, sizeof(res_tmpl));
339   res_tmpl.target = PIPE_TEXTURE_1D;
340   res_tmpl.format = colortbl_format;
341   res_tmpl.width0 = 1 << util_format_get_component_bits(
342      index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
343   res_tmpl.height0 = 1;
344   res_tmpl.depth0 = 1;
345   res_tmpl.array_size = 1;
346   res_tmpl.usage = PIPE_USAGE_STAGING;
347   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
348
349   res = context->screen->resource_create(context->screen, &res_tmpl);
350   if (!res)
351      goto error_resource;
352
353   box.x = box.y = box.z = 0;
354   box.width = res->width0;
355   box.height = res->height0;
356   box.depth = res->depth0;
357
358   context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
359                                  util_format_get_stride(colortbl_format, res->width0), 0);
360
361   memset(&sv_tmpl, 0, sizeof(sv_tmpl));
362   u_sampler_view_default_template(&sv_tmpl, res, res->format);
363
364   sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
365   pipe_resource_reference(&res, NULL);
366
367   if (!sv_tbl)
368      goto error_resource;
369
370   vl_compositor_clear_layers(cstate);
371   vl_compositor_set_palette_layer(cstate, compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
372   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
373   vl_compositor_render(cstate, compositor, vlsurface->surface, NULL);
374
375   pipe_sampler_view_reference(&sv_idx, NULL);
376   pipe_sampler_view_reference(&sv_tbl, NULL);
377
378   return VDP_STATUS_OK;
379
380error_resource:
381   pipe_sampler_view_reference(&sv_idx, NULL);
382   pipe_sampler_view_reference(&sv_tbl, NULL);
383   return VDP_STATUS_RESOURCES;
384}
385
386/**
387 * Copy image data from application memory in a specific YCbCr format to
388 * a VdpOutputSurface.
389 */
390VdpStatus
391vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
392                               VdpYCbCrFormat source_ycbcr_format,
393                               void const *const *source_data,
394                               uint32_t const *source_pitches,
395                               VdpRect const *destination_rect,
396                               VdpCSCMatrix const *csc_matrix)
397{
398   vlVdpOutputSurface *vlsurface;
399   struct vl_compositor *compositor;
400   struct vl_compositor_state *cstate;
401
402   struct pipe_context *pipe;
403   enum pipe_format format;
404   struct pipe_video_buffer vtmpl, *vbuffer;
405   struct u_rect dst_rect;
406   struct pipe_sampler_view **sampler_views;
407
408   unsigned i;
409
410   vlsurface = vlGetDataHTAB(surface);
411   if (!vlsurface)
412      return VDP_STATUS_INVALID_HANDLE;
413
414   vlVdpResolveDelayedRendering(vlsurface->device, NULL, NULL);
415
416   pipe = vlsurface->device->context;
417   compositor = &vlsurface->device->compositor;
418   cstate = &vlsurface->cstate;
419
420   format = FormatYCBCRToPipe(source_ycbcr_format);
421   if (format == PIPE_FORMAT_NONE)
422       return VDP_STATUS_INVALID_Y_CB_CR_FORMAT;
423
424   if (!source_data || !source_pitches)
425       return VDP_STATUS_INVALID_POINTER;
426
427   memset(&vtmpl, 0, sizeof(vtmpl));
428   vtmpl.buffer_format = format;
429   vtmpl.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420;
430
431   if (destination_rect) {
432      vtmpl.width = abs(destination_rect->x0-destination_rect->x1);
433      vtmpl.height = abs(destination_rect->y0-destination_rect->y1);
434   } else {
435      vtmpl.width = vlsurface->surface->texture->width0;
436      vtmpl.height = vlsurface->surface->texture->height0;
437   }
438
439   vbuffer = pipe->create_video_buffer(pipe, &vtmpl);
440   if (!vbuffer)
441      return VDP_STATUS_RESOURCES;
442
443   sampler_views = vbuffer->get_sampler_view_planes(vbuffer);
444   if (!sampler_views) {
445      vbuffer->destroy(vbuffer);
446      return VDP_STATUS_RESOURCES;
447   }
448
449   for (i = 0; i < 3; ++i) {
450      struct pipe_sampler_view *sv = sampler_views[i];
451      if (!sv) continue;
452
453      struct pipe_box dst_box = {
454         0, 0, 0,
455         sv->texture->width0, sv->texture->height0, 1
456      };
457
458      pipe->transfer_inline_write(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box,
459                                  source_data[i], source_pitches[i], 0);
460   }
461
462   if (!csc_matrix) {
463      vl_csc_matrix csc;
464      vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_BT_601, NULL, 1, &csc);
465      vl_compositor_set_csc_matrix(cstate, (const vl_csc_matrix*)&csc);
466   } else {
467      vl_compositor_set_csc_matrix(cstate, csc_matrix);
468   }
469
470   vl_compositor_clear_layers(cstate);
471   vl_compositor_set_buffer_layer(cstate, compositor, 0, vbuffer, NULL, NULL, VL_COMPOSITOR_WEAVE);
472   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
473   vl_compositor_render(cstate, compositor, vlsurface->surface, NULL);
474
475   vbuffer->destroy(vbuffer);
476
477   return VDP_STATUS_OK;
478}
479
480static unsigned
481BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
482{
483   switch (factor) {
484   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
485      return PIPE_BLENDFACTOR_ZERO;
486   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
487      return PIPE_BLENDFACTOR_ONE;
488   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
489      return PIPE_BLENDFACTOR_SRC_COLOR;
490   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
491      return PIPE_BLENDFACTOR_INV_SRC_COLOR;
492   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
493      return PIPE_BLENDFACTOR_SRC_ALPHA;
494   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
495      return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
496   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
497      return PIPE_BLENDFACTOR_DST_ALPHA;
498   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
499      return PIPE_BLENDFACTOR_INV_DST_ALPHA;
500   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
501      return PIPE_BLENDFACTOR_DST_COLOR;
502   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
503      return PIPE_BLENDFACTOR_INV_DST_COLOR;
504   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
505      return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
506   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
507      return PIPE_BLENDFACTOR_CONST_COLOR;
508   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
509      return PIPE_BLENDFACTOR_INV_CONST_COLOR;
510   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
511      return PIPE_BLENDFACTOR_CONST_ALPHA;
512   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
513      return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
514   default:
515      assert(0);
516      return PIPE_BLENDFACTOR_ONE;
517   }
518}
519
520static unsigned
521BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
522{
523   switch (equation) {
524   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
525      return PIPE_BLEND_SUBTRACT;
526   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
527      return PIPE_BLEND_REVERSE_SUBTRACT;
528   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
529      return PIPE_BLEND_ADD;
530   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
531      return PIPE_BLEND_MIN;
532   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
533      return PIPE_BLEND_MAX;
534   default:
535      assert(0);
536      return PIPE_BLEND_ADD;
537   }
538}
539
540static void *
541BlenderToPipe(struct pipe_context *context,
542              VdpOutputSurfaceRenderBlendState const *blend_state)
543{
544   struct pipe_blend_state blend;
545
546   memset(&blend, 0, sizeof blend);
547   blend.independent_blend_enable = 0;
548
549   if (blend_state) {
550      blend.rt[0].blend_enable = 1;
551      blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
552      blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
553      blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
554      blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
555      blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
556      blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
557   } else {
558      blend.rt[0].blend_enable = 0;
559   }
560
561   blend.logicop_enable = 0;
562   blend.logicop_func = PIPE_LOGICOP_CLEAR;
563   blend.rt[0].colormask = PIPE_MASK_RGBA;
564   blend.dither = 0;
565
566   return context->create_blend_state(context, &blend);
567}
568
569static struct vertex4f *
570ColorsToPipe(VdpColor const *colors, uint32_t flags, struct vertex4f result[4])
571{
572   unsigned i;
573   struct vertex4f *dst = result;
574
575   if (!colors)
576      return NULL;
577
578   for (i = 0; i < 4; ++i) {
579      dst->x = colors->red;
580      dst->y = colors->green;
581      dst->z = colors->blue;
582      dst->w = colors->alpha;
583
584      ++dst;
585      if (flags & VDP_OUTPUT_SURFACE_RENDER_COLOR_PER_VERTEX)
586         ++colors;
587   }
588   return result;
589}
590
591/**
592 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
593 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
594 */
595VdpStatus
596vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
597                                      VdpRect const *destination_rect,
598                                      VdpOutputSurface source_surface,
599                                      VdpRect const *source_rect,
600                                      VdpColor const *colors,
601                                      VdpOutputSurfaceRenderBlendState const *blend_state,
602                                      uint32_t flags)
603{
604   vlVdpOutputSurface *dst_vlsurface;
605   vlVdpOutputSurface *src_vlsurface;
606
607   struct pipe_context *context;
608   struct vl_compositor *compositor;
609   struct vl_compositor_state *cstate;
610
611   struct u_rect src_rect, dst_rect;
612
613   struct vertex4f vlcolors[4];
614   void *blend;
615
616   dst_vlsurface = vlGetDataHTAB(destination_surface);
617   if (!dst_vlsurface)
618      return VDP_STATUS_INVALID_HANDLE;
619
620   src_vlsurface = vlGetDataHTAB(source_surface);
621   if (!src_vlsurface)
622      return VDP_STATUS_INVALID_HANDLE;
623
624   if (dst_vlsurface->device != src_vlsurface->device)
625      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
626
627   vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
628
629   context = dst_vlsurface->device->context;
630   compositor = &dst_vlsurface->device->compositor;
631   cstate = &dst_vlsurface->cstate;
632
633   blend = BlenderToPipe(context, blend_state);
634
635   vl_compositor_clear_layers(cstate);
636   vl_compositor_set_layer_blend(cstate, 0, blend, false);
637   vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
638                                RectToPipe(source_rect, &src_rect), NULL,
639                                ColorsToPipe(colors, flags, vlcolors));
640   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
641   vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
642
643   context->delete_blend_state(context, blend);
644
645   return VDP_STATUS_OK;
646}
647
648/**
649 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
650 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
651 */
652VdpStatus
653vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
654                                      VdpRect const *destination_rect,
655                                      VdpBitmapSurface source_surface,
656                                      VdpRect const *source_rect,
657                                      VdpColor const *colors,
658                                      VdpOutputSurfaceRenderBlendState const *blend_state,
659                                      uint32_t flags)
660{
661   vlVdpOutputSurface *dst_vlsurface;
662   vlVdpBitmapSurface *src_vlsurface;
663
664   struct pipe_context *context;
665   struct vl_compositor *compositor;
666   struct vl_compositor_state *cstate;
667
668   struct u_rect src_rect, dst_rect;
669
670   struct vertex4f vlcolors[4];
671   void *blend;
672
673   dst_vlsurface = vlGetDataHTAB(destination_surface);
674   if (!dst_vlsurface)
675      return VDP_STATUS_INVALID_HANDLE;
676
677   src_vlsurface = vlGetDataHTAB(source_surface);
678   if (!src_vlsurface)
679      return VDP_STATUS_INVALID_HANDLE;
680
681   if (dst_vlsurface->device != src_vlsurface->device)
682      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
683
684   vlVdpResolveDelayedRendering(dst_vlsurface->device, NULL, NULL);
685
686   context = dst_vlsurface->device->context;
687   compositor = &dst_vlsurface->device->compositor;
688   cstate = &dst_vlsurface->cstate;
689
690   blend = BlenderToPipe(context, blend_state);
691
692   vl_compositor_clear_layers(cstate);
693   vl_compositor_set_layer_blend(cstate, 0, blend, false);
694   vl_compositor_set_rgba_layer(cstate, compositor, 0, src_vlsurface->sampler_view,
695                                RectToPipe(source_rect, &src_rect), NULL,
696                                ColorsToPipe(colors, flags, vlcolors));
697   vl_compositor_set_layer_dst_area(cstate, 0, RectToPipe(destination_rect, &dst_rect));
698   vl_compositor_render(cstate, compositor, dst_vlsurface->surface, NULL);
699
700   context->delete_blend_state(context, blend);
701
702   return VDP_STATUS_OK;
703}
704