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