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