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
;
148 tex
= _mesa_lookup_texture(ctx
, textureNames
[i
]);
151 _mesa_error(ctx
, GL_INVALID_OPERATION
,
152 "VDPAURegisterSurfaceNV(texture ID not found)");
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 else if (tex
->Target
!= target
) {
169 _mesa_unlock_texture(ctx
, tex
);
171 _mesa_error(ctx
, GL_INVALID_OPERATION
,
172 "VDPAURegisterSurfaceNV(target mismatch)");
173 return (GLintptr
)NULL
;
176 /* This will disallow respecifying the storage. */
177 tex
->Immutable
= GL_TRUE
;
178 _mesa_unlock_texture(ctx
, tex
);
180 _mesa_reference_texobj(&surf
->textures
[i
], tex
);
183 _mesa_set_add(ctx
->vdpSurfaces
, surf
);
185 return (GLintptr
)surf
;
189 _mesa_VDPAURegisterVideoSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
190 GLsizei numTextureNames
,
191 const GLuint
*textureNames
)
193 GET_CURRENT_CONTEXT(ctx
);
195 if (numTextureNames
!= 4) {
196 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
197 return (GLintptr
)NULL
;
200 return register_surface(ctx
, false, vdpSurface
, target
,
201 numTextureNames
, textureNames
);
205 _mesa_VDPAURegisterOutputSurfaceNV(const GLvoid
*vdpSurface
, GLenum target
,
206 GLsizei numTextureNames
,
207 const GLuint
*textureNames
)
209 GET_CURRENT_CONTEXT(ctx
);
211 if (numTextureNames
!= 1) {
212 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAURegisterVideoSurfaceNV");
213 return (GLintptr
)NULL
;
216 return register_surface(ctx
, true, vdpSurface
, target
,
217 numTextureNames
, textureNames
);
221 _mesa_VDPAUIsSurfaceNV(GLintptr surface
)
223 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
224 GET_CURRENT_CONTEXT(ctx
);
226 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
227 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUIsSurfaceNV");
231 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
239 _mesa_VDPAUUnregisterSurfaceNV(GLintptr surface
)
241 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
242 struct set_entry
*entry
;
244 GET_CURRENT_CONTEXT(ctx
);
246 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
247 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnregisterSurfaceNV");
251 /* according to the spec it's ok when this is zero */
255 entry
= _mesa_set_search(ctx
->vdpSurfaces
, surf
);
257 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUUnregisterSurfaceNV");
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
);
268 _mesa_set_remove(ctx
->vdpSurfaces
, entry
);
273 _mesa_VDPAUGetSurfaceivNV(GLintptr surface
, GLenum pname
, GLsizei bufSize
,
274 GLsizei
*length
, GLint
*values
)
276 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
277 GET_CURRENT_CONTEXT(ctx
);
279 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
280 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUGetSurfaceivNV");
284 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
285 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
289 if (pname
!= GL_SURFACE_STATE_NV
) {
290 _mesa_error(ctx
, GL_INVALID_ENUM
, "VDPAUGetSurfaceivNV");
295 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUGetSurfaceivNV");
299 values
[0] = surf
->state
;
306 _mesa_VDPAUSurfaceAccessNV(GLintptr surface
, GLenum access
)
308 struct vdp_surface
*surf
= (struct vdp_surface
*)surface
;
309 GET_CURRENT_CONTEXT(ctx
);
311 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
312 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
316 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
317 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
321 if (access
!= GL_READ_ONLY
&& access
!= GL_WRITE_ONLY
&&
322 access
!= GL_READ_WRITE
) {
324 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
328 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
329 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
333 surf
->access
= access
;
337 _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
339 GET_CURRENT_CONTEXT(ctx
);
342 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
343 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
347 for (i
= 0; i
< numSurfaces
; ++i
) {
348 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
350 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
351 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
355 if (surf
->state
== GL_SURFACE_MAPPED_NV
) {
356 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
361 for (i
= 0; i
< numSurfaces
; ++i
) {
362 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
363 unsigned numTextureNames
= surf
->output
? 1 : 4;
366 for (j
= 0; j
< numTextureNames
; ++j
) {
367 struct gl_texture_object
*tex
= surf
->textures
[j
];
368 struct gl_texture_image
*image
;
370 _mesa_lock_texture(ctx
, tex
);
371 image
= _mesa_get_tex_image(ctx
, tex
, surf
->target
, 0);
373 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "VDPAUMapSurfacesNV");
374 _mesa_unlock_texture(ctx
, tex
);
378 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
380 ctx
->Driver
.VDPAUMapSurface(ctx
, surf
->target
, surf
->access
,
381 surf
->output
, tex
, image
,
382 surf
->vdpSurface
, j
);
384 _mesa_unlock_texture(ctx
, tex
);
386 surf
->state
= GL_SURFACE_MAPPED_NV
;
391 _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces
, const GLintptr
*surfaces
)
393 GET_CURRENT_CONTEXT(ctx
);
396 if (!ctx
->vdpDevice
|| !ctx
->vdpGetProcAddress
|| !ctx
->vdpSurfaces
) {
397 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUUnmapSurfacesNV");
401 for (i
= 0; i
< numSurfaces
; ++i
) {
402 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
404 if (!_mesa_set_search(ctx
->vdpSurfaces
, surf
)) {
405 _mesa_error(ctx
, GL_INVALID_VALUE
, "VDPAUSurfaceAccessNV");
409 if (surf
->state
!= GL_SURFACE_MAPPED_NV
) {
410 _mesa_error(ctx
, GL_INVALID_OPERATION
, "VDPAUSurfaceAccessNV");
415 for (i
= 0; i
< numSurfaces
; ++i
) {
416 struct vdp_surface
*surf
= (struct vdp_surface
*)surfaces
[i
];
417 unsigned numTextureNames
= surf
->output
? 1 : 4;
420 for (j
= 0; j
< numTextureNames
; ++j
) {
421 struct gl_texture_object
*tex
= surf
->textures
[j
];
422 struct gl_texture_image
*image
;
424 _mesa_lock_texture(ctx
, tex
);
426 image
= _mesa_select_tex_image(tex
, surf
->target
, 0);
428 ctx
->Driver
.VDPAUUnmapSurface(ctx
, surf
->target
, surf
->access
,
429 surf
->output
, tex
, image
,
430 surf
->vdpSurface
, j
);
433 ctx
->Driver
.FreeTextureImageBuffer(ctx
, image
);
435 _mesa_unlock_texture(ctx
, tex
);
437 surf
->state
= GL_SURFACE_REGISTERED_NV
;