output.c revision 1448e829e86981e6144410ba6a3d0f16357fb2b3
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   memset(&sv_templ, 0, sizeof(sv_templ));
89   u_sampler_view_default_template(&sv_templ, res, res->format);
90   vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ);
91   if (!vlsurface->sampler_view) {
92      pipe_resource_reference(&res, NULL);
93      FREE(dev);
94      return VDP_STATUS_ERROR;
95   }
96
97   memset(&surf_templ, 0, sizeof(surf_templ));
98   surf_templ.format = res->format;
99   surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
100   vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ);
101   if (!vlsurface->surface) {
102      pipe_resource_reference(&res, NULL);
103      FREE(dev);
104      return VDP_STATUS_ERROR;
105   }
106
107   *surface = vlAddDataHTAB(vlsurface);
108   if (*surface == 0) {
109      pipe_resource_reference(&res, NULL);
110      FREE(dev);
111      return VDP_STATUS_ERROR;
112   }
113
114   pipe_resource_reference(&res, NULL);
115
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   pipe_surface_reference(&vlsurface->surface, NULL);
134   pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
135
136   vlRemoveDataHTAB(surface);
137   FREE(vlsurface);
138
139   return VDP_STATUS_OK;
140}
141
142/**
143 * Retrieve the parameters used to create a VdpOutputSurface.
144 */
145VdpStatus
146vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
147                                VdpRGBAFormat *rgba_format,
148                                uint32_t *width, uint32_t *height)
149{
150   vlVdpOutputSurface *vlsurface;
151
152   vlsurface = vlGetDataHTAB(surface);
153   if (!vlsurface)
154      return VDP_STATUS_INVALID_HANDLE;
155
156   *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
157   *width = vlsurface->sampler_view->texture->width0;
158   *height = vlsurface->sampler_view->texture->height0;
159
160   return VDP_STATUS_OK;
161}
162
163/**
164 * Copy image data from a VdpOutputSurface to application memory in the
165 * surface's native format.
166 */
167VdpStatus
168vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
169                                VdpRect const *source_rect,
170                                void *const *destination_data,
171                                uint32_t const *destination_pitches)
172{
173   return VDP_STATUS_NO_IMPLEMENTATION;
174}
175
176/**
177 * Copy image data from application memory in the surface's native format to
178 * a VdpOutputSurface.
179 */
180VdpStatus
181vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
182                                void const *const *source_data,
183                                uint32_t const *source_pitches,
184                                VdpRect const *destination_rect)
185{
186   return VDP_STATUS_NO_IMPLEMENTATION;
187}
188
189/**
190 * Copy image data from application memory in a specific indexed format to
191 * a VdpOutputSurface.
192 */
193VdpStatus
194vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
195                                 VdpIndexedFormat source_indexed_format,
196                                 void const *const *source_data,
197                                 uint32_t const *source_pitch,
198                                 VdpRect const *destination_rect,
199                                 VdpColorTableFormat color_table_format,
200                                 void const *color_table)
201{
202   vlVdpOutputSurface *vlsurface;
203   struct pipe_context *context;
204   struct vl_compositor *compositor;
205
206   enum pipe_format index_format;
207   enum pipe_format colortbl_format;
208
209   struct pipe_resource *res, res_tmpl;
210   struct pipe_sampler_view sv_tmpl;
211   struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
212
213   struct pipe_box box;
214   struct pipe_video_rect dst_rect;
215
216   vlsurface = vlGetDataHTAB(surface);
217   if (!vlsurface)
218      return VDP_STATUS_INVALID_HANDLE;
219
220   context = vlsurface->device->context;
221   compositor = &vlsurface->device->compositor;
222
223   index_format = FormatIndexedToPipe(source_indexed_format);
224   if (index_format == PIPE_FORMAT_NONE)
225       return VDP_STATUS_INVALID_INDEXED_FORMAT;
226
227   if (!source_data || !source_pitch)
228       return VDP_STATUS_INVALID_POINTER;
229
230   colortbl_format = FormatColorTableToPipe(color_table_format);
231   if (colortbl_format == PIPE_FORMAT_NONE)
232       return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
233
234   if (!color_table)
235       return VDP_STATUS_INVALID_POINTER;
236
237   memset(&res_tmpl, 0, sizeof(res_tmpl));
238   res_tmpl.target = PIPE_TEXTURE_2D;
239   res_tmpl.format = index_format;
240
241   if (destination_rect) {
242      res_tmpl.width0 = abs(destination_rect->x0-destination_rect->x1);
243      res_tmpl.height0 = abs(destination_rect->y0-destination_rect->y1);
244   } else {
245      res_tmpl.width0 = vlsurface->surface->texture->width0;
246      res_tmpl.height0 = vlsurface->surface->texture->height0;
247   }
248   res_tmpl.depth0 = 1;
249   res_tmpl.array_size = 1;
250   res_tmpl.usage = PIPE_USAGE_STAGING;
251   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
252
253   res = context->screen->resource_create(context->screen, &res_tmpl);
254   if (!res)
255      goto error_resource;
256
257   box.x = box.y = box.z = 0;
258   box.width = res->width0;
259   box.height = res->height0;
260   box.depth = res->depth0;
261
262   context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box,
263                                  source_data[0], source_pitch[0],
264                                  source_pitch[0] * res->height0);
265
266   memset(&sv_tmpl, 0, sizeof(sv_tmpl));
267   u_sampler_view_default_template(&sv_tmpl, res, res->format);
268
269   sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
270   pipe_resource_reference(&res, NULL);
271
272   if (!sv_idx)
273      goto error_resource;
274
275   memset(&res_tmpl, 0, sizeof(res_tmpl));
276   res_tmpl.target = PIPE_TEXTURE_1D;
277   res_tmpl.format = colortbl_format;
278   res_tmpl.width0 = 1 << util_format_get_component_bits(
279      index_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
280   res_tmpl.height0 = 1;
281   res_tmpl.depth0 = 1;
282   res_tmpl.array_size = 1;
283   res_tmpl.usage = PIPE_USAGE_STAGING;
284   res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
285
286   res = context->screen->resource_create(context->screen, &res_tmpl);
287   if (!res)
288      goto error_resource;
289
290   box.x = box.y = box.z = 0;
291   box.width = res->width0;
292   box.height = res->height0;
293   box.depth = res->depth0;
294
295   context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
296                                  util_format_get_stride(colortbl_format, res->width0), 0);
297
298   memset(&sv_tmpl, 0, sizeof(sv_tmpl));
299   u_sampler_view_default_template(&sv_tmpl, res, res->format);
300
301   sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
302   pipe_resource_reference(&res, NULL);
303
304   if (!sv_tbl)
305      goto error_resource;
306
307   vl_compositor_clear_layers(compositor);
308   vl_compositor_set_palette_layer(compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
309   vl_compositor_render(compositor, vlsurface->surface,
310                        RectToPipe(destination_rect, &dst_rect), NULL, NULL);
311
312   pipe_sampler_view_reference(&sv_idx, NULL);
313   pipe_sampler_view_reference(&sv_tbl, NULL);
314
315   return VDP_STATUS_OK;
316
317error_resource:
318   pipe_sampler_view_reference(&sv_idx, NULL);
319   pipe_sampler_view_reference(&sv_tbl, NULL);
320   return VDP_STATUS_RESOURCES;
321}
322
323/**
324 * Copy image data from application memory in a specific YCbCr format to
325 * a VdpOutputSurface.
326 */
327VdpStatus
328vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface,
329                               VdpYCbCrFormat source_ycbcr_format,
330                               void const *const *source_data,
331                               uint32_t const *source_pitches,
332                               VdpRect const *destination_rect,
333                               VdpCSCMatrix const *csc_matrix)
334{
335   return VDP_STATUS_NO_IMPLEMENTATION;
336}
337
338static unsigned
339BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor)
340{
341   switch (factor) {
342   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO:
343      return PIPE_BLENDFACTOR_ZERO;
344   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE:
345      return PIPE_BLENDFACTOR_ONE;
346   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR:
347      return PIPE_BLENDFACTOR_SRC_COLOR;
348   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR:
349      return PIPE_BLENDFACTOR_INV_SRC_COLOR;
350   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA:
351      return PIPE_BLENDFACTOR_SRC_ALPHA;
352   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA:
353      return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
354   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA:
355      return PIPE_BLENDFACTOR_DST_ALPHA;
356   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA:
357      return PIPE_BLENDFACTOR_INV_DST_ALPHA;
358   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR:
359      return PIPE_BLENDFACTOR_DST_COLOR;
360   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR:
361      return PIPE_BLENDFACTOR_INV_DST_COLOR;
362   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE:
363      return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
364   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR:
365      return PIPE_BLENDFACTOR_CONST_COLOR;
366   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR:
367      return PIPE_BLENDFACTOR_INV_CONST_COLOR;
368   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA:
369      return PIPE_BLENDFACTOR_CONST_ALPHA;
370   case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA:
371      return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
372   default:
373      assert(0);
374      return PIPE_BLENDFACTOR_ONE;
375   }
376}
377
378static unsigned
379BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation)
380{
381   switch (equation) {
382   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT:
383      return PIPE_BLEND_SUBTRACT;
384   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT:
385      return PIPE_BLEND_REVERSE_SUBTRACT;
386   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD:
387      return PIPE_BLEND_ADD;
388   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN:
389      return PIPE_BLEND_MIN;
390   case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX:
391      return PIPE_BLEND_MAX;
392   default:
393      assert(0);
394      return PIPE_BLEND_ADD;
395   }
396}
397
398static void *
399BlenderToPipe(struct pipe_context *context,
400              VdpOutputSurfaceRenderBlendState const *blend_state)
401{
402   struct pipe_blend_state blend;
403
404   memset(&blend, 0, sizeof blend);
405   blend.independent_blend_enable = 0;
406
407   if (blend_state) {
408      blend.rt[0].blend_enable = 1;
409      blend.rt[0].rgb_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_color);
410      blend.rt[0].rgb_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_color);
411      blend.rt[0].alpha_src_factor = BlendFactorToPipe(blend_state->blend_factor_source_alpha);
412      blend.rt[0].alpha_dst_factor = BlendFactorToPipe(blend_state->blend_factor_destination_alpha);
413      blend.rt[0].rgb_func = BlendEquationToPipe(blend_state->blend_equation_color);
414      blend.rt[0].alpha_func = BlendEquationToPipe(blend_state->blend_equation_alpha);
415   } else {
416      blend.rt[0].blend_enable = 0;
417   }
418
419   blend.logicop_enable = 0;
420   blend.logicop_func = PIPE_LOGICOP_CLEAR;
421   blend.rt[0].colormask = PIPE_MASK_RGBA;
422   blend.dither = 0;
423
424   return context->create_blend_state(context, &blend);
425}
426
427/**
428 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
429 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
430 */
431VdpStatus
432vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
433                                      VdpRect const *destination_rect,
434                                      VdpOutputSurface source_surface,
435                                      VdpRect const *source_rect,
436                                      VdpColor const *colors,
437                                      VdpOutputSurfaceRenderBlendState const *blend_state,
438                                      uint32_t flags)
439{
440   vlVdpOutputSurface *dst_vlsurface;
441   vlVdpOutputSurface *src_vlsurface;
442
443   struct pipe_context *context;
444   struct vl_compositor *compositor;
445
446   struct pipe_video_rect src_rect;
447   struct pipe_video_rect dst_rect;
448
449   void *blend;
450
451   dst_vlsurface = vlGetDataHTAB(destination_surface);
452   if (!dst_vlsurface)
453      return VDP_STATUS_INVALID_HANDLE;
454
455   src_vlsurface = vlGetDataHTAB(source_surface);
456   if (!src_vlsurface)
457      return VDP_STATUS_INVALID_HANDLE;
458
459   if (dst_vlsurface->device != src_vlsurface->device)
460      return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
461
462   context = dst_vlsurface->device->context;
463   compositor = &dst_vlsurface->device->compositor;
464
465   blend = BlenderToPipe(context, blend_state);
466
467   vl_compositor_clear_layers(compositor);
468   vl_compositor_set_layer_blend(compositor, 0, blend, false);
469   vl_compositor_set_rgba_layer(compositor, 0, src_vlsurface->sampler_view,
470                                RectToPipe(source_rect, &src_rect), NULL);
471   vl_compositor_render(compositor, dst_vlsurface->surface,
472                        RectToPipe(destination_rect, &dst_rect), NULL, false);
473
474   context->delete_blend_state(context, blend);
475
476   return VDP_STATUS_OK;
477}
478
479/**
480 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
481 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
482 */
483VdpStatus
484vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
485                                      VdpRect const *destination_rect,
486                                      VdpBitmapSurface source_surface,
487                                      VdpRect const *source_rect,
488                                      VdpColor const *colors,
489                                      VdpOutputSurfaceRenderBlendState const *blend_state,
490                                      uint32_t flags)
491{
492   return VDP_STATUS_NO_IMPLEMENTATION;
493}
494