3597576076f3d36abb9d01dbe2dfbd467bda6c90
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>
36 #include "glformats.h"
37 #include "hash_table.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
);
135 surf
->vdpSurface
= vdpSurface
;
136 surf
->target
= target
;
137 surf
->access
= GL_READ_WRITE
;
138 surf
->state
= GL_SURFACE_REGISTERED_NV
;
139 surf
->output
= isOutput
;
140 for (i
= 0; i
< numTextureNames
; ++i
) {
141 struct gl_texture_object
*tex
;
142 tex
= _mesa_lookup_texture(ctx
, textureNames
[i
]);
144 _mesa_lock_texture(ctx
, tex
);
146 if (tex
->Immutable
) {
147 _mesa_unlock_texture(ctx
, tex
);
149 _mesa_error(ctx
, GL_INVALID_OPERATION
,
150 "VDPAURegisterSurfaceNV(texture is immutable)");
151 return (GLintptr
)NULL
;
154 if (tex
->Target
== 0)
155 tex
->Target
= target
;
156 else if (tex
->Target
!= target
) {
157 _mesa_unlock_texture(ctx
, tex
);
159 _mesa_error(ctx
, GL_INVALID_OPERATION
,
160 "VDPAURegisterSurfaceNV(target mismatch)");
161 return (GLintptr
)NULL
;
164 /* This will disallow respecifying the storage. */
165 tex
->Immutable
= GL_TRUE
;
166 _mesa_unlock_texture(ctx
, tex
);
168 _mesa_reference_texobj(&surf
->textures
[i
], tex
);
171 _mesa_set_add(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
);
173 return (GLintptr
)surf
;
177 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
178 GLsizei numTextureNames
,
179 const GLuint
*textureNames
)
181 GET_CURRENT_CONTEXT(ctx
);
183 if (numTextureNames
!= 4) {
184 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
185 return (GLintptr
)NULL
;
188 return register_surface(ctx
, false, vdpSurface
, target
,
189 numTextureNames
, textureNames
);
193 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
194 GLsizei numTextureNames
,
195 const GLuint
*textureNames
)
197 GET_CURRENT_CONTEXT(ctx
);
199 if (numTextureNames
!= 1) {
200 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
201 return (GLintptr
)NULL
;
204 return register_surface(ctx
, true, vdpSurface
, target
,
205 numTextureNames
, textureNames
);
209 _mesa_VDPAUIsSurfaceNV(GLintptr surface
)
211 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
212 GET_CURRENT_CONTEXT(ctx
);
214 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
215 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUIsSurfaceNV");
219 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
220 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUIsSurfaceNV");
226 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface
)
228 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
229 struct set_entry
*entry
;
231 GET_CURRENT_CONTEXT(ctx
);
233 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
234 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnregisterSurfaceNV");
238 /* according to the spec it's ok when this is zero */
242 entry
= _mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
);
244 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUUnregisterSurfaceNV");
248 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
249 if (surf
->textures
[i
]) {
250 surf
->textures
[i
]->Immutable
= GL_FALSE
;
251 _mesa_reference_texobj(&surf
->textures
[i
], NULL
);
255 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
260 _mesa_VDPAUGetSurfaceivNV(GLintptr surface
, GLenum pname
, GLsizei bufSize
,
261 GLsizei
*length
, GLint
*values
)
263 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
264 GET_CURRENT_CONTEXT(ctx
);
266 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
267 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUGetSurfaceivNV");
271 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
272 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
276 if (pname
!= GL_SURFACE_STATE_NV
) {
277 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAUGetSurfaceivNV");
282 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
286 values
[0] = surf
->state
;
293 _mesa_VDPAUSurfaceAccessNV(GLintptr surface
, GLenum access
)
295 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
296 GET_CURRENT_CONTEXT(ctx
);
298 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
299 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
303 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
304 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
308 if (access
!= GL_READ_ONLY
&& access
!= GL_WRITE_ONLY
&&
309 access
!= GL_READ_WRITE
) {
311 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
315 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
316 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
320 surf
->access
= access
;
324 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
326 GET_CURRENT_CONTEXT(ctx
);
329 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
330 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
334 for (i
= 0; i
< numSurfaces
; ++i
) {
335 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
337 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
338 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
342 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
343 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
348 for (i
= 0; i
< numSurfaces
; ++i
) {
349 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
350 unsigned numTextureNames
= surf
->output
? 1 : 4;
353 for (j
= 0; j
< numTextureNames
; ++j
) {
354 struct gl_texture_object
*tex
= surf
->textures
[j
];
355 struct gl_texture_image
*image
;
357 _mesa_lock_texture(ctx
, tex
);
358 image
= _mesa_get_tex_image(ctx
, tex
, surf
->target
, 0);
360 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "VDPAUMapSurfacesNV");
361 _mesa_unlock_texture(ctx
, tex
);
365 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
367 ctx
->Driver
.VDPAUMapSurface(ctx
, surf
->target
, surf
->access
,
368 surf
->output
, tex
, image
,
369 surf
->vdpSurface
, j
);
371 _mesa_unlock_texture(ctx
, tex
);
373 surf
->state
= GL_SURFACE_MAPPED_NV
;
378 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
380 GET_CURRENT_CONTEXT(ctx
);
383 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
384 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
388 for (i
= 0; i
< numSurfaces
; ++i
) {
389 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
391 if (!_mesa_set_search(ctx
->vdpSurfaces
, _mesa_hash_pointer(surf
), surf
)) {
392 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
396 if (surf
->state
!= GL_SURFACE_MAPPED_NV
) {
397 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
402 for (i
= 0; i
< numSurfaces
; ++i
) {
403 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
404 unsigned numTextureNames
= surf
->output
? 1 : 4;
407 for (j
= 0; j
< numTextureNames
; ++j
) {
408 struct gl_texture_object
*tex
= surf
->textures
[j
];
409 struct gl_texture_image
*image
;
411 _mesa_lock_texture(ctx
, tex
);
413 image
= _mesa_select_tex_image(ctx
, tex
, surf
->target
, 0);
415 ctx
->Driver
.VDPAUUnmapSurface(ctx
, surf
->target
, surf
->access
,
416 surf
->output
, tex
, image
,
417 surf
->vdpSurface
, j
);
420 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
422 _mesa_unlock_texture(ctx
, tex
);
424 surf
->state
= GL_SURFACE_REGISTERED_NV
;