vl: rework winsys interface
[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_reset_dirty_area(&vlsurface->dirty_area);
117
118 return VDP_STATUS_OK;
119 }
120
121 /**
122 * Destroy a VdpOutputSurface.
123 */
124 VdpStatus
125 vlVdpOutputSurfaceDestroy(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 */
145 VdpStatus
146 vlVdpOutputSurfaceGetParameters(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 */
167 VdpStatus
168 vlVdpOutputSurfaceGetBitsNative(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 */
180 VdpStatus
181 vlVdpOutputSurfacePutBitsNative(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 */
193 VdpStatus
194 vlVdpOutputSurfacePutBitsIndexed(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
317 error_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 */
327 VdpStatus
328 vlVdpOutputSurfacePutBitsYCbCr(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
338 static unsigned
339 BlendFactorToPipe(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
378 static unsigned
379 BlendEquationToPipe(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
398 static void *
399 BlenderToPipe(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 */
431 VdpStatus
432 vlVdpOutputSurfaceRenderOutputSurface(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 */
483 VdpStatus
484 vlVdpOutputSurfaceRenderBitmapSurface(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 }