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
vl_compositor_reset_dirty_area(&vlsurface->dirty_area);
119
return VDP_STATUS_OK;
123
* Destroy a VdpOutputSurface.
126
vlVdpOutputSurfaceDestroy(VdpOutputSurface surface)
128
vlVdpOutputSurface *vlsurface;
130
VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying output surface\n");
132
vlsurface = vlGetDataHTAB(surface);
134
return VDP_STATUS_INVALID_HANDLE;
136
pipe_surface_reference(&vlsurface->surface, NULL);
137
pipe_sampler_view_reference(&vlsurface->sampler_view, NULL);
139
vlRemoveDataHTAB(surface);
142
return VDP_STATUS_OK;
146
* Retrieve the parameters used to create a VdpOutputSurface.
149
vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface,
150
VdpRGBAFormat *rgba_format,
151
uint32_t *width, uint32_t *height)
153
vlVdpOutputSurface *vlsurface;
155
VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Getting output surface parameters\n");
157
vlsurface = vlGetDataHTAB(surface);
159
return VDP_STATUS_INVALID_HANDLE;
161
*rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format);
162
*width = vlsurface->sampler_view->texture->width0;
163
*height = vlsurface->sampler_view->texture->height0;
165
return VDP_STATUS_OK;
169
* Copy image data from a VdpOutputSurface to application memory in the
170
* surface's native format.
173
vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface,
174
VdpRect const *source_rect,
175
void *const *destination_data,
176
uint32_t const *destination_pitches)
178
return VDP_STATUS_NO_IMPLEMENTATION;
182
* Copy image data from application memory in the surface's native format to
183
* a VdpOutputSurface.
186
vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface,
187
void const *const *source_data,
188
uint32_t const *source_pitches,
189
VdpRect const *destination_rect)
191
return VDP_STATUS_NO_IMPLEMENTATION;
195
* Copy image data from application memory in a specific indexed format to
196
* a VdpOutputSurface.
199
vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface,
200
VdpIndexedFormat source_indexed_format,
201
void const *const *source_data,
202
uint32_t const *source_pitch,
203
VdpRect const *destination_rect,
204
VdpColorTableFormat color_table_format,
205
void const *color_table)
207
vlVdpOutputSurface *vlsurface;
208
struct pipe_context *context;
209
struct vl_compositor *compositor;
211
enum pipe_format index_format;
212
enum pipe_format colortbl_format;
214
struct pipe_resource *res, res_tmpl;
215
struct pipe_sampler_view sv_tmpl;
216
struct pipe_sampler_view *sv_idx = NULL, *sv_tbl = NULL;
219
struct pipe_video_rect dst_rect;
221
VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Uploading indexed output surface\n");
223
vlsurface = vlGetDataHTAB(surface);
225
return VDP_STATUS_INVALID_HANDLE;
227
context = vlsurface->device->context->pipe;
228
compositor = &vlsurface->device->compositor;
230
index_format = FormatIndexedToPipe(source_indexed_format);
231
if (index_format == PIPE_FORMAT_NONE)
232
return VDP_STATUS_INVALID_INDEXED_FORMAT;
234
if (!source_data || !source_pitch)
235
return VDP_STATUS_INVALID_POINTER;
237
colortbl_format = FormatColorTableToPipe(color_table_format);
238
if (colortbl_format == PIPE_FORMAT_NONE)
239
return VDP_STATUS_INVALID_COLOR_TABLE_FORMAT;
242
return VDP_STATUS_INVALID_POINTER;
244
memset(&res_tmpl, 0, sizeof(res_tmpl));
245
res_tmpl.target = PIPE_TEXTURE_2D;
246
res_tmpl.format = index_format;
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);
252
res_tmpl.width0 = vlsurface->surface->texture->width0;
253
res_tmpl.height0 = vlsurface->surface->texture->height0;
256
res_tmpl.array_size = 1;
257
res_tmpl.usage = PIPE_USAGE_STAGING;
258
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
260
res = context->screen->resource_create(context->screen, &res_tmpl);
264
box.x = box.y = box.z = 0;
265
box.width = res->width0;
266
box.height = res->height0;
267
box.depth = res->depth0;
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);
273
memset(&sv_tmpl, 0, sizeof(sv_tmpl));
274
u_sampler_view_default_template(&sv_tmpl, res, res->format);
276
sv_idx = context->create_sampler_view(context, res, &sv_tmpl);
277
pipe_resource_reference(&res, NULL);
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;
289
res_tmpl.array_size = 1;
290
res_tmpl.usage = PIPE_USAGE_STAGING;
291
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
293
res = context->screen->resource_create(context->screen, &res_tmpl);
297
box.x = box.y = box.z = 0;
298
box.width = res->width0;
299
box.height = res->height0;
300
box.depth = res->depth0;
302
context->transfer_inline_write(context, res, 0, PIPE_TRANSFER_WRITE, &box, color_table,
303
util_format_get_stride(colortbl_format, res->width0), 0);
305
memset(&sv_tmpl, 0, sizeof(sv_tmpl));
306
u_sampler_view_default_template(&sv_tmpl, res, res->format);
308
sv_tbl = context->create_sampler_view(context, res, &sv_tmpl);
309
pipe_resource_reference(&res, NULL);
314
vl_compositor_clear_layers(compositor);
315
vl_compositor_set_palette_layer(compositor, 0, sv_idx, sv_tbl, NULL, NULL, false);
316
vl_compositor_render(compositor, vlsurface->surface,
317
RectToPipe(destination_rect, &dst_rect), NULL, NULL);
319
pipe_sampler_view_reference(&sv_idx, NULL);
320
pipe_sampler_view_reference(&sv_tbl, NULL);
322
return VDP_STATUS_OK;
325
pipe_sampler_view_reference(&sv_idx, NULL);
326
pipe_sampler_view_reference(&sv_tbl, NULL);
327
return VDP_STATUS_RESOURCES;
331
* Copy image data from application memory in a specific YCbCr format to
332
* a VdpOutputSurface.
335
vlVdpOutputSurfacePutBitsYCbCr(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)
342
return VDP_STATUS_NO_IMPLEMENTATION;
346
BlendFactorToPipe(VdpOutputSurfaceRenderBlendFactor 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;
381
return PIPE_BLENDFACTOR_ONE;
386
BlendEquationToPipe(VdpOutputSurfaceRenderBlendEquation 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;
401
return PIPE_BLEND_ADD;
406
BlenderToPipe(struct pipe_context *context,
407
VdpOutputSurfaceRenderBlendState const *blend_state)
409
struct pipe_blend_state blend;
411
memset(&blend, 0, sizeof blend);
412
blend.independent_blend_enable = 0;
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);
423
blend.rt[0].blend_enable = 0;
426
blend.logicop_enable = 0;
427
blend.logicop_func = PIPE_LOGICOP_CLEAR;
428
blend.rt[0].colormask = PIPE_MASK_RGBA;
431
return context->create_blend_state(context, &blend);
435
* Composite a sub-rectangle of a VdpOutputSurface into a sub-rectangle of
436
* another VdpOutputSurface; Output Surface object VdpOutputSurface.
439
vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface,
440
VdpRect const *destination_rect,
441
VdpOutputSurface source_surface,
442
VdpRect const *source_rect,
443
VdpColor const *colors,
444
VdpOutputSurfaceRenderBlendState const *blend_state,
447
vlVdpOutputSurface *dst_vlsurface;
448
vlVdpOutputSurface *src_vlsurface;
450
struct pipe_context *context;
451
struct vl_compositor *compositor;
453
struct pipe_video_rect src_rect;
454
struct pipe_video_rect dst_rect;
458
VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Composing output surfaces\n");
460
dst_vlsurface = vlGetDataHTAB(destination_surface);
462
return VDP_STATUS_INVALID_HANDLE;
464
src_vlsurface = vlGetDataHTAB(source_surface);
466
return VDP_STATUS_INVALID_HANDLE;
468
if (dst_vlsurface->device != src_vlsurface->device)
469
return VDP_STATUS_HANDLE_DEVICE_MISMATCH;
471
context = dst_vlsurface->device->context->pipe;
472
compositor = &dst_vlsurface->device->compositor;
474
blend = BlenderToPipe(context, blend_state);
476
vl_compositor_clear_layers(compositor);
477
vl_compositor_set_layer_blend(compositor, 0, blend, false);
478
vl_compositor_set_rgba_layer(compositor, 0, src_vlsurface->sampler_view,
479
RectToPipe(source_rect, &src_rect), NULL);
480
vl_compositor_render(compositor, dst_vlsurface->surface,
481
RectToPipe(destination_rect, &dst_rect), NULL, false);
483
context->delete_blend_state(context, blend);
485
return VDP_STATUS_OK;
489
* Composite a sub-rectangle of a VdpBitmapSurface into a sub-rectangle of
490
* a VdpOutputSurface; Output Surface object VdpOutputSurface.
493
vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface,
494
VdpRect const *destination_rect,
495
VdpBitmapSurface source_surface,
496
VdpRect const *source_rect,
497
VdpColor const *colors,
498
VdpOutputSurfaceRenderBlendState const *blend_state,
501
return VDP_STATUS_NO_IMPLEMENTATION;