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