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