1 /**************************************************************************
3 * Copyright 2010 Thomas Balling Sørensen.
4 * Copyright 2011 Christian König.
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:
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
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.
27 **************************************************************************/
29 #include <vdpau/vdpau.h>
31 #include "util/u_debug.h"
32 #include "util/u_memory.h"
33 #include "util/u_sampler.h"
34 #include "util/u_format.h"
36 #include "vdpau_private.h"
39 * Create a VdpOutputSurface.
42 vlVdpOutputSurfaceCreate(VdpDevice device
,
43 VdpRGBAFormat rgba_format
,
44 uint32_t width
, uint32_t height
,
45 VdpOutputSurface
*surface
)
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
;
52 vlVdpOutputSurface
*vlsurface
= NULL
;
54 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Creating output surface\n");
55 if (!(width
&& height
))
56 return VDP_STATUS_INVALID_SIZE
;
58 vlVdpDevice
*dev
= vlGetDataHTAB(device
);
60 return VDP_STATUS_INVALID_HANDLE
;
62 pipe
= dev
->context
->pipe
;
64 return VDP_STATUS_INVALID_HANDLE
;
66 vlsurface
= CALLOC(1, sizeof(vlVdpOutputSurface
));
68 return VDP_STATUS_RESOURCES
;
70 vlsurface
->device
= dev
;
72 memset(&res_tmpl
, 0, sizeof(res_tmpl
));
74 res_tmpl
.target
= PIPE_TEXTURE_2D
;
75 res_tmpl
.format
= FormatRGBAToPipe(rgba_format
);
76 res_tmpl
.width0
= width
;
77 res_tmpl
.height0
= height
;
79 res_tmpl
.array_size
= 1;
80 res_tmpl
.bind
= PIPE_BIND_SAMPLER_VIEW
| PIPE_BIND_RENDER_TARGET
;
81 res_tmpl
.usage
= PIPE_USAGE_STATIC
;
83 res
= pipe
->screen
->resource_create(pipe
->screen
, &res_tmpl
);
86 return VDP_STATUS_ERROR
;
89 memset(&sv_templ
, 0, sizeof(sv_templ
));
90 u_sampler_view_default_template(&sv_templ
, res
, res
->format
);
91 vlsurface
->sampler_view
= pipe
->create_sampler_view(pipe
, res
, &sv_templ
);
92 if (!vlsurface
->sampler_view
) {
93 pipe_resource_reference(&res
, NULL
);
95 return VDP_STATUS_ERROR
;
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
);
105 return VDP_STATUS_ERROR
;
108 *surface
= vlAddDataHTAB(vlsurface
);
110 pipe_resource_reference(&res
, NULL
);
112 return VDP_STATUS_ERROR
;
115 pipe_resource_reference(&res
, NULL
);
117 return VDP_STATUS_OK
;
121 * Destroy a VdpOutputSurface.
124 vlVdpOutputSurfaceDestroy(VdpOutputSurface surface
)
126 vlVdpOutputSurface
*vlsurface
;
128 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Destroying output surface\n");
130 vlsurface
= vlGetDataHTAB(surface
);
132 return VDP_STATUS_INVALID_HANDLE
;
134 pipe_surface_reference(&vlsurface
->surface
, NULL
);
135 pipe_sampler_view_reference(&vlsurface
->sampler_view
, NULL
);
137 vlRemoveDataHTAB(surface
);
140 return VDP_STATUS_OK
;
144 * Retrieve the parameters used to create a VdpOutputSurface.
147 vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface
,
148 VdpRGBAFormat
*rgba_format
,
149 uint32_t *width
, uint32_t *height
)
151 vlVdpOutputSurface
*vlsurface
;
153 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Getting output surface parameters\n");
155 vlsurface
= vlGetDataHTAB(surface
);
157 return VDP_STATUS_INVALID_HANDLE
;
159 *rgba_format
= PipeToFormatRGBA(vlsurface
->sampler_view
->texture
->format
);
160 *width
= vlsurface
->sampler_view
->texture
->width0
;
161 *height
= vlsurface
->sampler_view
->texture
->height0
;
163 return VDP_STATUS_OK
;
167 * Copy image data from a VdpOutputSurface to application memory in the
168 * surface's native format.
171 vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface
,
172 VdpRect
const *source_rect
,
173 void *const *destination_data
,
174 uint32_t const *destination_pitches
)
176 return VDP_STATUS_NO_IMPLEMENTATION
;
180 * Copy image data from application memory in the surface's native format to
181 * a VdpOutputSurface.
184 vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface
,
185 void const *const *source_data
,
186 uint32_t const *source_pitches
,
187 VdpRect
const *destination_rect
)
189 return VDP_STATUS_NO_IMPLEMENTATION
;
193 * Copy image data from application memory in a specific indexed format to
194 * a VdpOutputSurface.
197 vlVdpOutputSurfacePutBitsIndexed(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
)
205 vlVdpOutputSurface
*vlsurface
;
206 struct pipe_context
*context
;
207 struct vl_compositor
*compositor
;
209 enum pipe_format index_format
;
210 enum pipe_format colortbl_format
;
212 struct pipe_resource
*res
, res_tmpl
;
213 struct pipe_sampler_view sv_tmpl
;
214 struct pipe_sampler_view
*sv_idx
= NULL
, *sv_tbl
= NULL
;
217 struct pipe_video_rect dst_rect
;
219 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Uploading indexed output surface\n");
221 vlsurface
= vlGetDataHTAB(surface
);
223 return VDP_STATUS_INVALID_HANDLE
;
225 context
= vlsurface
->device
->context
->pipe
;
226 compositor
= &vlsurface
->device
->compositor
;
228 index_format
= FormatIndexedToPipe(source_indexed_format
);
229 if (index_format
== PIPE_FORMAT_NONE
)
230 return VDP_STATUS_INVALID_INDEXED_FORMAT
;
232 if (!source_data
|| !source_pitch
)
233 return VDP_STATUS_INVALID_POINTER
;
235 colortbl_format
= FormatColorTableToPipe(color_table_format
);
236 if (colortbl_format
== PIPE_FORMAT_NONE
)
237 return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT
;
240 return VDP_STATUS_INVALID_POINTER
;
242 memset(&res_tmpl
, 0, sizeof(res_tmpl
));
243 res_tmpl
.target
= PIPE_TEXTURE_2D
;
244 res_tmpl
.format
= index_format
;
246 if (destination_rect
) {
247 res_tmpl
.width0
= abs(destination_rect
->x0
-destination_rect
->x1
);
248 res_tmpl
.height0
= abs(destination_rect
->y0
-destination_rect
->y1
);
250 res_tmpl
.width0
= vlsurface
->surface
->texture
->width0
;
251 res_tmpl
.height0
= vlsurface
->surface
->texture
->height0
;
254 res_tmpl
.array_size
= 1;
255 res_tmpl
.usage
= PIPE_USAGE_STAGING
;
256 res_tmpl
.bind
= PIPE_BIND_SAMPLER_VIEW
;
258 res
= context
->screen
->resource_create(context
->screen
, &res_tmpl
);
262 box
.x
= box
.y
= box
.z
= 0;
263 box
.width
= res
->width0
;
264 box
.height
= res
->height0
;
265 box
.depth
= res
->depth0
;
267 context
->transfer_inline_write(context
, res
, 0, PIPE_TRANSFER_WRITE
, &box
,
268 source_data
[0], source_pitch
[0],
269 source_pitch
[0] * res
->height0
);
271 memset(&sv_tmpl
, 0, sizeof(sv_tmpl
));
272 u_sampler_view_default_template(&sv_tmpl
, res
, res
->format
);
274 sv_idx
= context
->create_sampler_view(context
, res
, &sv_tmpl
);
275 pipe_resource_reference(&res
, NULL
);
280 memset(&res_tmpl
, 0, sizeof(res_tmpl
));
281 res_tmpl
.target
= PIPE_TEXTURE_1D
;
282 res_tmpl
.format
= colortbl_format
;
283 res_tmpl
.width0
= 1 << util_format_get_component_bits(
284 index_format
, UTIL_FORMAT_COLORSPACE_RGB
, 0);
285 res_tmpl
.height0
= 1;
287 res_tmpl
.array_size
= 1;
288 res_tmpl
.usage
= PIPE_USAGE_STAGING
;
289 res_tmpl
.bind
= PIPE_BIND_SAMPLER_VIEW
;
291 res
= context
->screen
->resource_create(context
->screen
, &res_tmpl
);
295 box
.x
= box
.y
= box
.z
= 0;
296 box
.width
= res
->width0
;
297 box
.height
= res
->height0
;
298 box
.depth
= res
->depth0
;
300 context
->transfer_inline_write(context
, res
, 0, PIPE_TRANSFER_WRITE
, &box
, color_table
,
301 util_format_get_stride(colortbl_format
, res
->width0
), 0);
303 memset(&sv_tmpl
, 0, sizeof(sv_tmpl
));
304 u_sampler_view_default_template(&sv_tmpl
, res
, res
->format
);
306 sv_tbl
= context
->create_sampler_view(context
, res
, &sv_tmpl
);
307 pipe_resource_reference(&res
, NULL
);
312 vl_compositor_clear_layers(compositor
);
313 vl_compositor_set_palette_layer(compositor
, 0, sv_idx
, sv_tbl
, NULL
, NULL
, false);
314 vl_compositor_render(compositor
, vlsurface
->surface
,
315 RectToPipe(destination_rect
, &dst_rect
), NULL
, false);
317 pipe_sampler_view_reference(&sv_idx
, NULL
);
318 pipe_sampler_view_reference(&sv_tbl
, NULL
);
320 return VDP_STATUS_OK
;
323 pipe_sampler_view_reference(&sv_idx
, NULL
);
324 pipe_sampler_view_reference(&sv_tbl
, NULL
);
325 return VDP_STATUS_RESOURCES
;
329 * Copy image data from application memory in a specific YCbCr format to
330 * a VdpOutputSurface.
333 vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface
,
334 VdpYCbCrFormat source_ycbcr_format
,
335 void const *const *source_data
,
336 uint32_t const *source_pitches
,
337 VdpRect
const *destination_rect
,
338 VdpCSCMatrix
const *csc_matrix
)
340 return VDP_STATUS_NO_IMPLEMENTATION
;
344 BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor factor
)
347 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO
:
348 return PIPE_BLENDFACTOR_ZERO
;
349 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE
:
350 return PIPE_BLENDFACTOR_ONE
;
351 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_COLOR
:
352 return PIPE_BLENDFACTOR_SRC_COLOR
;
353 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR
:
354 return PIPE_BLENDFACTOR_INV_SRC_COLOR
;
355 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA
:
356 return PIPE_BLENDFACTOR_SRC_ALPHA
;
357 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
:
358 return PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
359 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_ALPHA
:
360 return PIPE_BLENDFACTOR_DST_ALPHA
;
361 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_ALPHA
:
362 return PIPE_BLENDFACTOR_INV_DST_ALPHA
;
363 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_DST_COLOR
:
364 return PIPE_BLENDFACTOR_DST_COLOR
;
365 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_DST_COLOR
:
366 return PIPE_BLENDFACTOR_INV_DST_COLOR
;
367 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA_SATURATE
:
368 return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE
;
369 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_COLOR
:
370 return PIPE_BLENDFACTOR_CONST_COLOR
;
371 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR
:
372 return PIPE_BLENDFACTOR_INV_CONST_COLOR
;
373 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_CONSTANT_ALPHA
:
374 return PIPE_BLENDFACTOR_CONST_ALPHA
;
375 case VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA
:
376 return PIPE_BLENDFACTOR_INV_CONST_ALPHA
;
379 return PIPE_BLENDFACTOR_ONE
;
384 BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation equation
)
387 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_SUBTRACT
:
388 return PIPE_BLEND_SUBTRACT
;
389 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_REVERSE_SUBTRACT
:
390 return PIPE_BLEND_REVERSE_SUBTRACT
;
391 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD
:
392 return PIPE_BLEND_ADD
;
393 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MIN
:
394 return PIPE_BLEND_MIN
;
395 case VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_MAX
:
396 return PIPE_BLEND_MAX
;
399 return PIPE_BLEND_ADD
;
404 BlenderToPipe(struct pipe_context
*context
,
405 VdpOutputSurfaceRenderBlendState
const *blend_state
)
407 struct pipe_blend_state blend
;
409 memset(&blend
, 0, sizeof blend
);
410 blend
.independent_blend_enable
= 0;
413 blend
.rt
[0].blend_enable
= 1;
414 blend
.rt
[0].rgb_src_factor
= BlendFactorToPipe(blend_state
->blend_factor_source_color
);
415 blend
.rt
[0].rgb_dst_factor
= BlendFactorToPipe(blend_state
->blend_factor_destination_color
);
416 blend
.rt
[0].alpha_src_factor
= BlendFactorToPipe(blend_state
->blend_factor_source_alpha
);
417 blend
.rt
[0].alpha_dst_factor
= BlendFactorToPipe(blend_state
->blend_factor_destination_alpha
);
418 blend
.rt
[0].rgb_func
= BlendEquationToPipe(blend_state
->blend_equation_color
);
419 blend
.rt
[0].alpha_func
= BlendEquationToPipe(blend_state
->blend_equation_alpha
);
421 blend
.rt
[0].blend_enable
= 0;
424 blend
.logicop_enable
= 0;
425 blend
.logicop_func
= PIPE_LOGICOP_CLEAR
;
426 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
429 return context
->create_blend_state(context
, &blend
);
433 * Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
434 * another VdpOutputSurface; Output Surface object VdpOutputSurface.
437 vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface
,
438 VdpRect
const *destination_rect
,
439 VdpOutputSurface source_surface
,
440 VdpRect
const *source_rect
,
441 VdpColor
const *colors
,
442 VdpOutputSurfaceRenderBlendState
const *blend_state
,
445 vlVdpOutputSurface
*dst_vlsurface
;
446 vlVdpOutputSurface
*src_vlsurface
;
448 struct pipe_context
*context
;
449 struct vl_compositor
*compositor
;
451 struct pipe_video_rect src_rect
;
452 struct pipe_video_rect dst_rect
;
456 VDPAU_MSG(VDPAU_TRACE
, "[VDPAU] Composing output surfaces\n");
458 dst_vlsurface
= vlGetDataHTAB(destination_surface
);
460 return VDP_STATUS_INVALID_HANDLE
;
462 src_vlsurface
= vlGetDataHTAB(source_surface
);
464 return VDP_STATUS_INVALID_HANDLE
;
466 if (dst_vlsurface
->device
!= src_vlsurface
->device
)
467 return VDP_STATUS_HANDLE_DEVICE_MISMATCH
;
469 context
= dst_vlsurface
->device
->context
->pipe
;
470 compositor
= &dst_vlsurface
->device
->compositor
;
472 blend
= BlenderToPipe(context
, blend_state
);
474 vl_compositor_clear_layers(compositor
);
475 vl_compositor_set_layer_blend(compositor
, 0, blend
, false);
476 vl_compositor_set_rgba_layer(compositor
, 0, src_vlsurface
->sampler_view
,
477 RectToPipe(source_rect
, &src_rect
), NULL
);
478 vl_compositor_render(compositor
, dst_vlsurface
->surface
,
479 RectToPipe(destination_rect
, &dst_rect
), NULL
, false);
481 context
->delete_blend_state(context
, blend
);
483 return VDP_STATUS_OK
;
487 * Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
488 * a VdpOutputSurface; Output Surface object VdpOutputSurface.
491 vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface
,
492 VdpRect
const *destination_rect
,
493 VdpBitmapSurface source_surface
,
494 VdpRect
const *source_rect
,
495 VdpColor
const *colors
,
496 VdpOutputSurfaceRenderBlendState
const *blend_state
,
499 return VDP_STATUS_NO_IMPLEMENTATION
;