main: Fix whitespace in teximage.c.
[mesa.git] / src / mesa / main / vdpau.c
1 /**************************************************************************
2 *
3 * Copyright 2013 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Christian König <christian.koenig@amd.com>
31 *
32 */
33
34 #include <stdbool.h>
35 #include "util/hash_table.h"
36 #include "util/set.h"
37 #include "context.h"
38 #include "glformats.h"
39 #include "texobj.h"
40 #include "teximage.h"
41 #include "vdpau.h"
42
43 #define MAX_TEXTURES 4
44
45 struct vdp_surface
46 {
47 GLenum target;
48 struct gl_texture_object *textures[MAX_TEXTURES];
49 GLenum access, state;
50 GLboolean output;
51 const GLvoid *vdpSurface;
52 };
53
54 void GLAPIENTRY
55 _mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress)
56 {
57 GET_CURRENT_CONTEXT(ctx);
58
59 if (!vdpDevice) {
60 _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice");
61 return;
62 }
63
64 if (!getProcAddress) {
65 _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress");
66 return;
67 }
68
69 if (ctx->vdpDevice || ctx->vdpGetProcAddress || ctx->vdpSurfaces) {
70 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV");
71 return;
72 }
73
74 ctx->vdpDevice = vdpDevice;
75 ctx->vdpGetProcAddress = getProcAddress;
76 ctx->vdpSurfaces = _mesa_set_create(NULL, _mesa_hash_pointer,
77 _mesa_key_pointer_equal);
78 }
79
80 static void
81 unregister_surface(struct set_entry *entry)
82 {
83 struct vdp_surface *surf = (struct vdp_surface *)entry->key;
84 GET_CURRENT_CONTEXT(ctx);
85
86 if (surf->state == GL_SURFACE_MAPPED_NV) {
87 GLintptr surfaces[] = { (GLintptr)surf };
88 _mesa_VDPAUUnmapSurfacesNV(1, surfaces);
89 }
90
91 _mesa_set_remove(ctx->vdpSurfaces, entry);
92 free(surf);
93 }
94
95 void GLAPIENTRY
96 _mesa_VDPAUFiniNV(void)
97 {
98 GET_CURRENT_CONTEXT(ctx);
99
100 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
101 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV");
102 return;
103 }
104
105 _mesa_set_destroy(ctx->vdpSurfaces, unregister_surface);
106
107 ctx->vdpDevice = 0;
108 ctx->vdpGetProcAddress = 0;
109 ctx->vdpSurfaces = NULL;
110 }
111
112 static GLintptr
113 register_surface(struct gl_context *ctx, GLboolean isOutput,
114 const GLvoid *vdpSurface, GLenum target,
115 GLsizei numTextureNames, const GLuint *textureNames)
116 {
117 struct vdp_surface *surf;
118 int i;
119
120 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
121 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV");
122 return (GLintptr)NULL;
123 }
124
125 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) {
126 _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
127 return (GLintptr)NULL;
128 }
129
130 if (target == GL_TEXTURE_RECTANGLE && !ctx->Extensions.NV_texture_rectangle) {
131 _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV");
132 return (GLintptr)NULL;
133 }
134
135 surf = CALLOC_STRUCT( vdp_surface );
136 if (surf == NULL) {
137 _mesa_error_no_memory("VDPAURegisterSurfaceNV");
138 return (GLintptr)NULL;
139 }
140
141 surf->vdpSurface = vdpSurface;
142 surf->target = target;
143 surf->access = GL_READ_WRITE;
144 surf->state = GL_SURFACE_REGISTERED_NV;
145 surf->output = isOutput;
146 for (i = 0; i < numTextureNames; ++i) {
147 struct gl_texture_object *tex;
148 tex = _mesa_lookup_texture(ctx, textureNames[i]);
149 if (tex == NULL) {
150 free(surf);
151 _mesa_error(ctx, GL_INVALID_OPERATION,
152 "VDPAURegisterSurfaceNV(texture ID not found)");
153 return (GLintptr)NULL;
154 }
155
156 _mesa_lock_texture(ctx, tex);
157
158 if (tex->Immutable) {
159 _mesa_unlock_texture(ctx, tex);
160 free(surf);
161 _mesa_error(ctx, GL_INVALID_OPERATION,
162 "VDPAURegisterSurfaceNV(texture is immutable)");
163 return (GLintptr)NULL;
164 }
165
166 if (tex->Target == 0)
167 tex->Target = target;
168 else if (tex->Target != target) {
169 _mesa_unlock_texture(ctx, tex);
170 free(surf);
171 _mesa_error(ctx, GL_INVALID_OPERATION,
172 "VDPAURegisterSurfaceNV(target mismatch)");
173 return (GLintptr)NULL;
174 }
175
176 /* This will disallow respecifying the storage. */
177 tex->Immutable = GL_TRUE;
178 _mesa_unlock_texture(ctx, tex);
179
180 _mesa_reference_texobj(&surf->textures[i], tex);
181 }
182
183 _mesa_set_add(ctx->vdpSurfaces, surf);
184
185 return (GLintptr)surf;
186 }
187
188 GLintptr GLAPIENTRY
189 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target,
190 GLsizei numTextureNames,
191 const GLuint *textureNames)
192 {
193 GET_CURRENT_CONTEXT(ctx);
194
195 if (numTextureNames != 4) {
196 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
197 return (GLintptr)NULL;
198 }
199
200 return register_surface(ctx, false, vdpSurface, target,
201 numTextureNames, textureNames);
202 }
203
204 GLintptr GLAPIENTRY
205 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target,
206 GLsizei numTextureNames,
207 const GLuint *textureNames)
208 {
209 GET_CURRENT_CONTEXT(ctx);
210
211 if (numTextureNames != 1) {
212 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV");
213 return (GLintptr)NULL;
214 }
215
216 return register_surface(ctx, true, vdpSurface, target,
217 numTextureNames, textureNames);
218 }
219
220 GLboolean GLAPIENTRY
221 _mesa_VDPAUIsSurfaceNV(GLintptr surface)
222 {
223 struct vdp_surface *surf = (struct vdp_surface *)surface;
224 GET_CURRENT_CONTEXT(ctx);
225
226 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
227 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV");
228 return false;
229 }
230
231 if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
232 return false;
233 }
234
235 return true;
236 }
237
238 void GLAPIENTRY
239 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface)
240 {
241 struct vdp_surface *surf = (struct vdp_surface *)surface;
242 struct set_entry *entry;
243 int i;
244 GET_CURRENT_CONTEXT(ctx);
245
246 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
247 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnregisterSurfaceNV");
248 return;
249 }
250
251 /* according to the spec it's ok when this is zero */
252 if (surface == 0)
253 return;
254
255 entry = _mesa_set_search(ctx->vdpSurfaces, surf);
256 if (!entry) {
257 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUUnregisterSurfaceNV");
258 return;
259 }
260
261 for (i = 0; i < MAX_TEXTURES; i++) {
262 if (surf->textures[i]) {
263 surf->textures[i]->Immutable = GL_FALSE;
264 _mesa_reference_texobj(&surf->textures[i], NULL);
265 }
266 }
267
268 _mesa_set_remove(ctx->vdpSurfaces, entry);
269 free(surf);
270 }
271
272 void GLAPIENTRY
273 _mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize,
274 GLsizei *length, GLint *values)
275 {
276 struct vdp_surface *surf = (struct vdp_surface *)surface;
277 GET_CURRENT_CONTEXT(ctx);
278
279 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
280 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV");
281 return;
282 }
283
284 if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
285 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
286 return;
287 }
288
289 if (pname != GL_SURFACE_STATE_NV) {
290 _mesa_error(ctx, GL_INVALID_ENUM, "VDPAUGetSurfaceivNV");
291 return;
292 }
293
294 if (bufSize < 1) {
295 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUGetSurfaceivNV");
296 return;
297 }
298
299 values[0] = surf->state;
300
301 if (length != NULL)
302 *length = 1;
303 }
304
305 void GLAPIENTRY
306 _mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access)
307 {
308 struct vdp_surface *surf = (struct vdp_surface *)surface;
309 GET_CURRENT_CONTEXT(ctx);
310
311 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
312 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
313 return;
314 }
315
316 if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
317 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
318 return;
319 }
320
321 if (access != GL_READ_ONLY && access != GL_WRITE_ONLY &&
322 access != GL_READ_WRITE) {
323
324 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
325 return;
326 }
327
328 if (surf->state == GL_SURFACE_MAPPED_NV) {
329 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
330 return;
331 }
332
333 surf->access = access;
334 }
335
336 void GLAPIENTRY
337 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
338 {
339 GET_CURRENT_CONTEXT(ctx);
340 int i;
341
342 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
343 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
344 return;
345 }
346
347 for (i = 0; i < numSurfaces; ++i) {
348 struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
349
350 if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
351 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
352 return;
353 }
354
355 if (surf->state == GL_SURFACE_MAPPED_NV) {
356 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
357 return;
358 }
359 }
360
361 for (i = 0; i < numSurfaces; ++i) {
362 struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
363 unsigned numTextureNames = surf->output ? 1 : 4;
364 unsigned j;
365
366 for (j = 0; j < numTextureNames; ++j) {
367 struct gl_texture_object *tex = surf->textures[j];
368 struct gl_texture_image *image;
369
370 _mesa_lock_texture(ctx, tex);
371 image = _mesa_get_tex_image(ctx, tex, surf->target, 0);
372 if (!image) {
373 _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV");
374 _mesa_unlock_texture(ctx, tex);
375 return;
376 }
377
378 ctx->Driver.FreeTextureImageBuffer(ctx, image);
379
380 ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access,
381 surf->output, tex, image,
382 surf->vdpSurface, j);
383
384 _mesa_unlock_texture(ctx, tex);
385 }
386 surf->state = GL_SURFACE_MAPPED_NV;
387 }
388 }
389
390 void GLAPIENTRY
391 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
392 {
393 GET_CURRENT_CONTEXT(ctx);
394 int i;
395
396 if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
397 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
398 return;
399 }
400
401 for (i = 0; i < numSurfaces; ++i) {
402 struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
403
404 if (!_mesa_set_search(ctx->vdpSurfaces, surf)) {
405 _mesa_error(ctx, GL_INVALID_VALUE, "VDPAUSurfaceAccessNV");
406 return;
407 }
408
409 if (surf->state != GL_SURFACE_MAPPED_NV) {
410 _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV");
411 return;
412 }
413 }
414
415 for (i = 0; i < numSurfaces; ++i) {
416 struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
417 unsigned numTextureNames = surf->output ? 1 : 4;
418 unsigned j;
419
420 for (j = 0; j < numTextureNames; ++j) {
421 struct gl_texture_object *tex = surf->textures[j];
422 struct gl_texture_image *image;
423
424 _mesa_lock_texture(ctx, tex);
425
426 image = _mesa_select_tex_image(tex, surf->target, 0);
427
428 ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access,
429 surf->output, tex, image,
430 surf->vdpSurface, j);
431
432 if (image)
433 ctx->Driver.FreeTextureImageBuffer(ctx, image);
434
435 _mesa_unlock_texture(ctx, tex);
436 }
437 surf->state = GL_SURFACE_REGISTERED_NV;
438 }
439 }