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_key_pointer_equal
);
80 unregister_surface(struct set_entry
*entry
)
82 struct vdp_surface
*surf
= (struct vdp_surface
*)entry
->key
;
83 GET_CURRENT_CONTEXT(ctx
);
85 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
86 GLintptr surfaces
[] = { (GLintptr
)surf
};
87 _mesa_VDPAUUnmapSurfacesNV(1, surfaces
);
90 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
95 _mesa_VDPAUFiniNV(void)
97 GET_CURRENT_CONTEXT(ctx
);
99 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
100 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUFiniNV");
104 _mesa_set_destroy(ctx
->vdpSurfaces
, unregister_surface
);
107 ctx
->vdpGetProcAddress
= 0;
108 ctx
->vdpSurfaces
= NULL
;
112 register_surface(struct gl_context
*ctx
, GLboolean isOutput
,
113 const GLvoid
*vdpSurface
, GLenum target
,
114 GLsizei numTextureNames
, const GLuint
*textureNames
)
116 struct vdp_surface
*surf
;
119 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
120 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAURegisterSurfaceNV");
121 return (GLintptr
)NULL
;
124 if (target
!= GL_TEXTURE_2D
&& target
!= GL_TEXTURE_RECTANGLE
) {
125 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
126 return (GLintptr
)NULL
;
129 if (target
== GL_TEXTURE_RECTANGLE
&& !ctx
->Extensions
.NV_texture_rectangle
) {
130 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAURegisterSurfaceNV");
131 return (GLintptr
)NULL
;
134 surf
= CALLOC_STRUCT( vdp_surface
);
136 _mesa_error_no_memory("VDPAURegisterSurfaceNV");
137 return (GLintptr
)NULL
;
140 surf
->vdpSurface
= vdpSurface
;
141 surf
->target
= target
;
142 surf
->access
= GL_READ_WRITE
;
143 surf
->state
= GL_SURFACE_REGISTERED_NV
;
144 surf
->output
= isOutput
;
145 for (i
= 0; i
< numTextureNames
; ++i
) {
146 struct gl_texture_object
*tex
;
147 tex
= _mesa_lookup_texture(ctx
, textureNames
[i
]);
150 _mesa_error(ctx
, GL_INVALID_OPERATION
,
151 "VDPAURegisterSurfaceNV(texture ID not found)");
152 return (GLintptr
)NULL
;
155 _mesa_lock_texture(ctx
, tex
);
157 if (tex
->Immutable
) {
158 _mesa_unlock_texture(ctx
, tex
);
160 _mesa_error(ctx
, GL_INVALID_OPERATION
,
161 "VDPAURegisterSurfaceNV(texture is immutable)");
162 return (GLintptr
)NULL
;
165 if (tex
->Target
== 0)
166 tex
->Target
= target
;
167 else if (tex
->Target
!= target
) {
168 _mesa_unlock_texture(ctx
, tex
);
170 _mesa_error(ctx
, GL_INVALID_OPERATION
,
171 "VDPAURegisterSurfaceNV(target mismatch)");
172 return (GLintptr
)NULL
;
175 /* This will disallow respecifying the storage. */
176 tex
->Immutable
= GL_TRUE
;
177 _mesa_unlock_texture(ctx
, tex
);
179 _mesa_reference_texobj(&surf
->textures
[i
], tex
);
182 _mesa_set_add(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
);
184 return (GLintptr
)surf
;
188 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
189 GLsizei numTextureNames
,
190 const GLuint
*textureNames
)
192 GET_CURRENT_CONTEXT(ctx
);
194 if (numTextureNames
!= 4) {
195 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
196 return (GLintptr
)NULL
;
199 return register_surface(ctx
, false, vdpSurface
, target
,
200 numTextureNames
, textureNames
);
204 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
205 GLsizei numTextureNames
,
206 const GLuint
*textureNames
)
208 GET_CURRENT_CONTEXT(ctx
);
210 if (numTextureNames
!= 1) {
211 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
212 return (GLintptr
)NULL
;
215 return register_surface(ctx
, true, vdpSurface
, target
,
216 numTextureNames
, textureNames
);
220 _mesa_VDPAUIsSurfaceNV(GLintptr surface
)
222 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
223 GET_CURRENT_CONTEXT(ctx
);
225 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
226 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUIsSurfaceNV");
230 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
238 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface
)
240 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
241 struct set_entry
*entry
;
243 GET_CURRENT_CONTEXT(ctx
);
245 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
246 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnregisterSurfaceNV");
250 /* according to the spec it's ok when this is zero */
254 entry
= _mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
);
256 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUUnregisterSurfaceNV");
260 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
261 if (surf
->textures
[i
]) {
262 surf
->textures
[i
]->Immutable
= GL_FALSE
;
263 _mesa_reference_texobj(&surf
->textures
[i
], NULL
);
267 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
272 _mesa_VDPAUGetSurfaceivNV(GLintptr surface
, GLenum pname
, GLsizei bufSize
,
273 GLsizei
*length
, GLint
*values
)
275 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
276 GET_CURRENT_CONTEXT(ctx
);
278 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
279 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUGetSurfaceivNV");
283 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
284 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
288 if (pname
!= GL_SURFACE_STATE_NV
) {
289 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAUGetSurfaceivNV");
294 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
298 values
[0] = surf
->state
;
305 _mesa_VDPAUSurfaceAccessNV(GLintptr surface
, GLenum access
)
307 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
308 GET_CURRENT_CONTEXT(ctx
);
310 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
311 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
315 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
316 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
320 if (access
!= GL_READ_ONLY
&& access
!= GL_WRITE_ONLY
&&
321 access
!= GL_READ_WRITE
) {
323 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
327 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
328 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
332 surf
->access
= access
;
336 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
338 GET_CURRENT_CONTEXT(ctx
);
341 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
342 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
346 for (i
= 0; i
< numSurfaces
; ++i
) {
347 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
349 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
350 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
354 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
355 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
360 for (i
= 0; i
< numSurfaces
; ++i
) {
361 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
362 unsigned numTextureNames
= surf
->output
? 1 : 4;
365 for (j
= 0; j
< numTextureNames
; ++j
) {
366 struct gl_texture_object
*tex
= surf
->textures
[j
];
367 struct gl_texture_image
*image
;
369 _mesa_lock_texture(ctx
, tex
);
370 image
= _mesa_get_tex_image(ctx
, tex
, surf
->target
, 0);
372 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "VDPAUMapSurfacesNV");
373 _mesa_unlock_texture(ctx
, tex
);
377 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
379 ctx
->Driver
.VDPAUMapSurface(ctx
, surf
->target
, surf
->access
,
380 surf
->output
, tex
, image
,
381 surf
->vdpSurface
, j
);
383 _mesa_unlock_texture(ctx
, tex
);
385 surf
->state
= GL_SURFACE_MAPPED_NV
;
390 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
392 GET_CURRENT_CONTEXT(ctx
);
395 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
396 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
400 for (i
= 0; i
< numSurfaces
; ++i
) {
401 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
403 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
404 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
408 if (surf
->state
!= GL_SURFACE_MAPPED_NV
) {
409 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
414 for (i
= 0; i
< numSurfaces
; ++i
) {
415 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
416 unsigned numTextureNames
= surf
->output
? 1 : 4;
419 for (j
= 0; j
< numTextureNames
; ++j
) {
420 struct gl_texture_object
*tex
= surf
->textures
[j
];
421 struct gl_texture_image
*image
;
423 _mesa_lock_texture(ctx
, tex
);
425 image
= _mesa_select_tex_image(tex
, surf
->target
, 0);
427 ctx
->Driver
.VDPAUUnmapSurface(ctx
, surf
->target
, surf
->access
,
428 surf
->output
, tex
, image
,
429 surf
->vdpSurface
, j
);
432 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
434 _mesa_unlock_texture(ctx
, tex
);
436 surf
->state
= GL_SURFACE_REGISTERED_NV
;