051071beb5fa4f745e0cf70a4f95cc954c725b68
1 /**************************************************************************
3 * Copyright 2013 Advanced Micro Devices, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Christian König <christian.koenig@amd.com>
35 #include "util/hash_table.h"
38 #include "glformats.h"
43 #define MAX_TEXTURES 4
48 struct gl_texture_object
*textures
[MAX_TEXTURES
];
51 const GLvoid
*vdpSurface
;
55 _mesa_VDPAUInitNV(const GLvoid
*vdpDevice
, const GLvoid
*getProcAddress
)
57 GET_CURRENT_CONTEXT(ctx
);
60 _mesa_error(ctx
, GL_INVALID_VALUE
, "vdpDevice");
64 if (!getProcAddress
) {
65 _mesa_error(ctx
, GL_INVALID_VALUE
, "getProcAddress");
69 if (ctx
->vdpDevice
|| ctx
->vdpGetProcAddress
|| ctx
->vdpSurfaces
) {
70 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUInitNV");
74 ctx
->vdpDevice
= vdpDevice
;
75 ctx
->vdpGetProcAddress
= getProcAddress
;
76 ctx
->vdpSurfaces
= _mesa_set_create(NULL
, _mesa_hash_pointer
,
77 _mesa_key_pointer_equal
);
81 unregister_surface(struct set_entry
*entry
)
83 struct vdp_surface
*surf
= (struct vdp_surface
*)entry
->key
;
84 GET_CURRENT_CONTEXT(ctx
);
86 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
87 GLintptr surfaces
[] = { (GLintptr
)surf
};
88 _mesa_VDPAUUnmapSurfacesNV(1, surfaces
);
91 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
96 _mesa_VDPAUFiniNV(void)
98 GET_CURRENT_CONTEXT(ctx
);
100 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
101 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUFiniNV");
105 _mesa_set_destroy(ctx
->vdpSurfaces
, unregister_surface
);
108 ctx
->vdpGetProcAddress
= 0;
109 ctx
->vdpSurfaces
= NULL
;
113 register_surface(struct gl_context
*ctx
, GLboolean isOutput
,
114 const GLvoid
*vdpSurface
, GLenum target
,
115 GLsizei numTextureNames
, const GLuint
*textureNames
)
117 struct vdp_surface
*surf
;
120 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
121 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAURegisterSurfaceNV");
122 return (GLintptr
)NULL
;
125 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE
) {
126 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
127 return (GLintptr
)NULL
;
130 if (target
== GL_TEXTURE_RECTANGLE
&& !ctx
->Extensions
.NV_texture_rectangle
) {
131 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
132 return (GLintptr
)NULL
;
135 surf
= CALLOC_STRUCT( vdp_surface
);
137 _mesa_error_no_memory("VDPAURegisterSurfaceNV");
138 return (GLintptr
)NULL
;
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
;
149 tex
= _mesa_lookup_texture_err(ctx
, textureNames
[i
],
150 "VDPAURegisterSurfaceNV");
153 return (GLintptr
)NULL
;
156 _mesa_lock_texture(ctx
, tex
);
158 if (tex
->Immutable
) {
159 _mesa_unlock_texture(ctx
, tex
);
161 _mesa_error(ctx
, GL_INVALID_OPERATION
,
162 "VDPAURegisterSurfaceNV(texture is immutable)");
163 return (GLintptr
)NULL
;
166 if (tex
->Target
== 0) {
167 tex
->Target
= target
;
168 tex
->TargetIndex
= _mesa_tex_target_to_index(ctx
, target
);
169 } else if (tex
->Target
!= target
) {
170 _mesa_unlock_texture(ctx
, tex
);
172 _mesa_error(ctx
, GL_INVALID_OPERATION
,
173 "VDPAURegisterSurfaceNV(target mismatch)");
174 return (GLintptr
)NULL
;
177 /* This will disallow respecifying the storage. */
178 tex
->Immutable
= GL_TRUE
;
179 _mesa_unlock_texture(ctx
, tex
);
181 _mesa_reference_texobj(&surf
->textures
[i
], tex
);
184 _mesa_set_add(ctx
->vdpSurfaces
, surf
);
186 return (GLintptr
)surf
;
190 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
191 GLsizei numTextureNames
,
192 const GLuint
*textureNames
)
194 GET_CURRENT_CONTEXT(ctx
);
196 if (numTextureNames
!= 4) {
197 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
198 return (GLintptr
)NULL
;
201 return register_surface(ctx
, false, vdpSurface
, target
,
202 numTextureNames
, textureNames
);
206 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
207 GLsizei numTextureNames
,
208 const GLuint
*textureNames
)
210 GET_CURRENT_CONTEXT(ctx
);
212 if (numTextureNames
!= 1) {
213 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
214 return (GLintptr
)NULL
;
217 return register_surface(ctx
, true, vdpSurface
, target
,
218 numTextureNames
, textureNames
);
222 _mesa_VDPAUIsSurfaceNV(GLintptr surface
)
224 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
225 GET_CURRENT_CONTEXT(ctx
);
227 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
228 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUIsSurfaceNV");
232 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
240 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface
)
242 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
243 struct set_entry
*entry
;
245 GET_CURRENT_CONTEXT(ctx
);
247 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
248 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnregisterSurfaceNV");
252 /* according to the spec it's ok when this is zero */
256 entry
= _mesa_set_search(ctx
->vdpSurfaces
, surf
);
258 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUUnregisterSurfaceNV");
262 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
263 if (surf
->textures
[i
]) {
264 surf
->textures
[i
]->Immutable
= GL_FALSE
;
265 _mesa_reference_texobj(&surf
->textures
[i
], NULL
);
269 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
274 _mesa_VDPAUGetSurfaceivNV(GLintptr surface
, GLenum pname
, GLsizei bufSize
,
275 GLsizei
*length
, GLint
*values
)
277 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
278 GET_CURRENT_CONTEXT(ctx
);
280 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
281 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUGetSurfaceivNV");
285 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
286 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
290 if (pname
!= GL_SURFACE_STATE_NV
) {
291 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAUGetSurfaceivNV");
296 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
300 values
[0] = surf
->state
;
307 _mesa_VDPAUSurfaceAccessNV(GLintptr surface
, GLenum access
)
309 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
310 GET_CURRENT_CONTEXT(ctx
);
312 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
313 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
317 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
318 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
322 if (access
!= GL_READ_ONLY
&& access
!= GL_WRITE_ONLY
&&
323 access
!= GL_READ_WRITE
) {
325 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
329 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
330 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
334 surf
->access
= access
;
338 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
340 GET_CURRENT_CONTEXT(ctx
);
343 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
344 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
348 for (i
= 0; i
< numSurfaces
; ++i
) {
349 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
351 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
352 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
356 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
357 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
362 for (i
= 0; i
< numSurfaces
; ++i
) {
363 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
364 unsigned numTextureNames
= surf
->output
? 1 : 4;
367 for (j
= 0; j
< numTextureNames
; ++j
) {
368 struct gl_texture_object
*tex
= surf
->textures
[j
];
369 struct gl_texture_image
*image
;
371 _mesa_lock_texture(ctx
, tex
);
372 image
= _mesa_get_tex_image(ctx
, tex
, surf
->target
, 0);
374 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "VDPAUMapSurfacesNV");
375 _mesa_unlock_texture(ctx
, tex
);
379 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
381 ctx
->Driver
.VDPAUMapSurface(ctx
, surf
->target
, surf
->access
,
382 surf
->output
, tex
, image
,
383 surf
->vdpSurface
, j
);
385 _mesa_unlock_texture(ctx
, tex
);
387 surf
->state
= GL_SURFACE_MAPPED_NV
;
392 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
394 GET_CURRENT_CONTEXT(ctx
);
397 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
398 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
402 for (i
= 0; i
< numSurfaces
; ++i
) {
403 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
405 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
406 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
410 if (surf
->state
!= GL_SURFACE_MAPPED_NV
) {
411 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
416 for (i
= 0; i
< numSurfaces
; ++i
) {
417 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
418 unsigned numTextureNames
= surf
->output
? 1 : 4;
421 for (j
= 0; j
< numTextureNames
; ++j
) {
422 struct gl_texture_object
*tex
= surf
->textures
[j
];
423 struct gl_texture_image
*image
;
425 _mesa_lock_texture(ctx
, tex
);
427 image
= _mesa_select_tex_image(tex
, surf
->target
, 0);
429 ctx
->Driver
.VDPAUUnmapSurface(ctx
, surf
->target
, surf
->access
,
430 surf
->output
, tex
, image
,
431 surf
->vdpSurface
, j
);
434 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
436 _mesa_unlock_texture(ctx
, tex
);
438 surf
->state
= GL_SURFACE_REGISTERED_NV
;