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"
37 #include "util/u_memory.h"
39 #include "glformats.h"
44 #define MAX_TEXTURES 4
49 struct gl_texture_object
*textures
[MAX_TEXTURES
];
52 const GLvoid
*vdpSurface
;
56 _mesa_VDPAUInitNV(const GLvoid
*vdpDevice
, const GLvoid
*getProcAddress
)
58 GET_CURRENT_CONTEXT(ctx
);
61 _mesa_error(ctx
, GL_INVALID_VALUE
, "vdpDevice");
65 if (!getProcAddress
) {
66 _mesa_error(ctx
, GL_INVALID_VALUE
, "getProcAddress");
70 if (ctx
->vdpDevice
|| ctx
->vdpGetProcAddress
|| ctx
->vdpSurfaces
) {
71 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUInitNV");
75 ctx
->vdpDevice
= vdpDevice
;
76 ctx
->vdpGetProcAddress
= getProcAddress
;
77 ctx
->vdpSurfaces
= _mesa_set_create(NULL
, _mesa_hash_pointer
,
78 _mesa_key_pointer_equal
);
82 unregister_surface(struct set_entry
*entry
)
84 struct vdp_surface
*surf
= (struct vdp_surface
*)entry
->key
;
85 GET_CURRENT_CONTEXT(ctx
);
87 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
88 GLintptr surfaces
[] = { (GLintptr
)surf
};
89 _mesa_VDPAUUnmapSurfacesNV(1, surfaces
);
92 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
97 _mesa_VDPAUFiniNV(void)
99 GET_CURRENT_CONTEXT(ctx
);
101 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
102 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUFiniNV");
106 _mesa_set_destroy(ctx
->vdpSurfaces
, unregister_surface
);
109 ctx
->vdpGetProcAddress
= 0;
110 ctx
->vdpSurfaces
= NULL
;
114 register_surface(struct gl_context
*ctx
, GLboolean isOutput
,
115 const GLvoid
*vdpSurface
, GLenum target
,
116 GLsizei numTextureNames
, const GLuint
*textureNames
)
118 struct vdp_surface
*surf
;
121 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
122 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAURegisterSurfaceNV");
123 return (GLintptr
)NULL
;
126 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE
) {
127 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
128 return (GLintptr
)NULL
;
131 if (target
== GL_TEXTURE_RECTANGLE
&& !ctx
->Extensions
.NV_texture_rectangle
) {
132 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
133 return (GLintptr
)NULL
;
136 surf
= CALLOC_STRUCT( vdp_surface
);
138 _mesa_error_no_memory("VDPAURegisterSurfaceNV");
139 return (GLintptr
)NULL
;
142 surf
->vdpSurface
= vdpSurface
;
143 surf
->target
= target
;
144 surf
->access
= GL_READ_WRITE
;
145 surf
->state
= GL_SURFACE_REGISTERED_NV
;
146 surf
->output
= isOutput
;
147 for (i
= 0; i
< numTextureNames
; ++i
) {
148 struct gl_texture_object
*tex
;
150 tex
= _mesa_lookup_texture_err(ctx
, textureNames
[i
],
151 "VDPAURegisterSurfaceNV");
154 return (GLintptr
)NULL
;
157 _mesa_lock_texture(ctx
, tex
);
159 if (tex
->Immutable
) {
160 _mesa_unlock_texture(ctx
, tex
);
162 _mesa_error(ctx
, GL_INVALID_OPERATION
,
163 "VDPAURegisterSurfaceNV(texture is immutable)");
164 return (GLintptr
)NULL
;
167 if (tex
->Target
== 0) {
168 tex
->Target
= target
;
169 tex
->TargetIndex
= _mesa_tex_target_to_index(ctx
, target
);
170 } else if (tex
->Target
!= target
) {
171 _mesa_unlock_texture(ctx
, tex
);
173 _mesa_error(ctx
, GL_INVALID_OPERATION
,
174 "VDPAURegisterSurfaceNV(target mismatch)");
175 return (GLintptr
)NULL
;
178 /* This will disallow respecifying the storage. */
179 tex
->Immutable
= GL_TRUE
;
180 _mesa_unlock_texture(ctx
, tex
);
182 _mesa_reference_texobj(&surf
->textures
[i
], tex
);
185 _mesa_set_add(ctx
->vdpSurfaces
, surf
);
187 return (GLintptr
)surf
;
191 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
192 GLsizei numTextureNames
,
193 const GLuint
*textureNames
)
195 GET_CURRENT_CONTEXT(ctx
);
197 if (numTextureNames
!= 4) {
198 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
199 return (GLintptr
)NULL
;
202 return register_surface(ctx
, false, vdpSurface
, target
,
203 numTextureNames
, textureNames
);
207 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
208 GLsizei numTextureNames
,
209 const GLuint
*textureNames
)
211 GET_CURRENT_CONTEXT(ctx
);
213 if (numTextureNames
!= 1) {
214 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
215 return (GLintptr
)NULL
;
218 return register_surface(ctx
, true, vdpSurface
, target
,
219 numTextureNames
, textureNames
);
223 _mesa_VDPAUIsSurfaceNV(GLintptr surface
)
225 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
226 GET_CURRENT_CONTEXT(ctx
);
228 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
229 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUIsSurfaceNV");
233 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
241 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface
)
243 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
244 struct set_entry
*entry
;
246 GET_CURRENT_CONTEXT(ctx
);
248 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
249 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnregisterSurfaceNV");
253 /* according to the spec it's ok when this is zero */
257 entry
= _mesa_set_search(ctx
->vdpSurfaces
, surf
);
259 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUUnregisterSurfaceNV");
263 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
264 if (surf
->textures
[i
]) {
265 surf
->textures
[i
]->Immutable
= GL_FALSE
;
266 _mesa_reference_texobj(&surf
->textures
[i
], NULL
);
270 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
275 _mesa_VDPAUGetSurfaceivNV(GLintptr surface
, GLenum pname
, GLsizei bufSize
,
276 GLsizei
*length
, GLint
*values
)
278 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
279 GET_CURRENT_CONTEXT(ctx
);
281 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
282 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUGetSurfaceivNV");
286 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
287 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
291 if (pname
!= GL_SURFACE_STATE_NV
) {
292 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAUGetSurfaceivNV");
297 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
301 values
[0] = surf
->state
;
308 _mesa_VDPAUSurfaceAccessNV(GLintptr surface
, GLenum access
)
310 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
311 GET_CURRENT_CONTEXT(ctx
);
313 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
314 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
318 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
319 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
323 if (access
!= GL_READ_ONLY
&& access
!= GL_WRITE_ONLY
&&
324 access
!= GL_READ_WRITE
) {
326 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
330 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
331 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
335 surf
->access
= access
;
339 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
341 GET_CURRENT_CONTEXT(ctx
);
344 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
345 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
349 for (i
= 0; i
< numSurfaces
; ++i
) {
350 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
352 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
353 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
357 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
358 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
363 for (i
= 0; i
< numSurfaces
; ++i
) {
364 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
365 unsigned numTextureNames
= surf
->output
? 1 : 4;
368 for (j
= 0; j
< numTextureNames
; ++j
) {
369 struct gl_texture_object
*tex
= surf
->textures
[j
];
370 struct gl_texture_image
*image
;
372 _mesa_lock_texture(ctx
, tex
);
373 image
= _mesa_get_tex_image(ctx
, tex
, surf
->target
, 0);
375 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "VDPAUMapSurfacesNV");
376 _mesa_unlock_texture(ctx
, tex
);
380 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
382 ctx
->Driver
.VDPAUMapSurface(ctx
, surf
->target
, surf
->access
,
383 surf
->output
, tex
, image
,
384 surf
->vdpSurface
, j
);
386 _mesa_unlock_texture(ctx
, tex
);
388 surf
->state
= GL_SURFACE_MAPPED_NV
;
393 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
395 GET_CURRENT_CONTEXT(ctx
);
398 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
399 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
403 for (i
= 0; i
< numSurfaces
; ++i
) {
404 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
406 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
407 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
411 if (surf
->state
!= GL_SURFACE_MAPPED_NV
) {
412 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
417 for (i
= 0; i
< numSurfaces
; ++i
) {
418 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
419 unsigned numTextureNames
= surf
->output
? 1 : 4;
422 for (j
= 0; j
< numTextureNames
; ++j
) {
423 struct gl_texture_object
*tex
= surf
->textures
[j
];
424 struct gl_texture_image
*image
;
426 _mesa_lock_texture(ctx
, tex
);
428 image
= _mesa_select_tex_image(tex
, surf
->target
, 0);
430 ctx
->Driver
.VDPAUUnmapSurface(ctx
, surf
->target
, surf
->access
,
431 surf
->output
, tex
, image
,
432 surf
->vdpSurface
, j
);
435 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
437 _mesa_unlock_texture(ctx
, tex
);
439 surf
->state
= GL_SURFACE_REGISTERED_NV
;