#include "macros.h"
#include "mtypes.h"
+#include "bufferobj.h"
+#include "context.h"
#include "externalobjects.h"
+#include "teximage.h"
+#include "texobj.h"
+#include "glformats.h"
+#include "texstorage.h"
+#include "util/u_memory.h"
/**
* Allocate and initialize a new memory object. But don't put it into the
memoryObjects);
}
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glDeleteMemoryObjectsEXT(unsupported)");
+ return;
+ }
+
if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "glDeleteMemoryObjectsEXT(n < 0)");
return;
_mesa_IsMemoryObjectEXT(GLuint memoryObject)
{
GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glIsMemoryObjectEXT(unsupported)");
+ return GL_FALSE;
+ }
+
struct gl_memory_object *obj =
_mesa_lookup_memory_object(ctx, memoryObject);
if (MESA_VERBOSE & (VERBOSE_API))
_mesa_debug(ctx, "%s(%d, %p)", func, n, memoryObjects);
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
if (n < 0) {
_mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
return;
GET_CURRENT_CONTEXT(ctx);
struct gl_memory_object *memObj;
+ const char *func = "glMemoryObjectParameterivEXT";
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
memObj = _mesa_lookup_memory_object(ctx, memoryObject);
if (!memObj)
return;
if (memObj->Immutable) {
- _mesa_error(ctx, GL_INVALID_OPERATION,
- "glMemoryObjectParameterivEXT(memoryObject is immutable");
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(memoryObject is immutable", func);
return;
}
return;
invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glMemoryObjectParameterivEXT(pname=0x%x)", pname);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
}
void GLAPIENTRY
GET_CURRENT_CONTEXT(ctx);
struct gl_memory_object *memObj;
+ const char *func = "glMemoryObjectParameterivEXT";
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
memObj = _mesa_lookup_memory_object(ctx, memoryObject);
if (!memObj)
return;
return;
invalid_pname:
- _mesa_error(ctx, GL_INVALID_ENUM,
- "glGetMemoryObjectParameterivEXT(pname=0x%x)", pname);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
+}
+
+static struct gl_memory_object *
+lookup_memory_object_err(struct gl_context *ctx, unsigned memory,
+ const char* func)
+{
+ if (memory == 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(memory=0)", func);
+ return NULL;
+ }
+
+ struct gl_memory_object *memObj = _mesa_lookup_memory_object(ctx, memory);
+ if (!memObj)
+ return NULL;
+
+ if (!memObj->Immutable) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no associated memory)",
+ func);
+ return NULL;
+ }
+
+ return memObj;
+}
+
+/**
+ * Helper used by _mesa_TexStorageMem1/2/3DEXT().
+ */
+static void
+texstorage_memory(GLuint dims, GLenum target, GLsizei levels,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLsizei depth, GLuint memory, GLuint64 offset,
+ const char *func)
+{
+ struct gl_texture_object *texObj;
+ struct gl_memory_object *memObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ if (!texObj)
+ return;
+
+ memObj = lookup_memory_object_err(ctx, memory, func);
+ if (!memObj)
+ return;
+
+ _mesa_texture_storage_memory(ctx, dims, texObj, memObj, target,
+ levels, internalFormat,
+ width, height, depth, offset, false);
+}
+
+static void
+texstorage_memory_ms(GLuint dims, GLenum target, GLsizei samples,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLsizei depth, GLboolean fixedSampleLocations,
+ GLuint memory, GLuint64 offset, const char* func)
+{
+ struct gl_texture_object *texObj;
+ struct gl_memory_object *memObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ texObj = _mesa_get_current_tex_object(ctx, target);
+ if (!texObj)
+ return;
+
+ memObj = lookup_memory_object_err(ctx, memory, func);
+ if (!memObj)
+ return;
+
+ _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, target, samples,
+ internalFormat, width, height, depth,
+ fixedSampleLocations, offset, func);
+}
+
+/**
+ * Helper used by _mesa_TextureStorageMem1/2/3DEXT().
+ */
+static void
+texturestorage_memory(GLuint dims, GLuint texture, GLsizei levels,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLsizei depth, GLuint memory, GLuint64 offset,
+ const char *func)
+{
+ struct gl_texture_object *texObj;
+ struct gl_memory_object *memObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ texObj = _mesa_lookup_texture(ctx, texture);
+ if (!texObj)
+ return;
+
+ memObj = lookup_memory_object_err(ctx, memory, func);
+ if (!memObj)
+ return;
+
+ _mesa_texture_storage_memory(ctx, dims, texObj, memObj, texObj->Target,
+ levels, internalFormat,
+ width, height, depth, offset, true);
+}
+
+static void
+texturestorage_memory_ms(GLuint dims, GLuint texture, GLsizei samples,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLsizei depth, GLboolean fixedSampleLocations,
+ GLuint memory, GLuint64 offset, const char* func)
+{
+ struct gl_texture_object *texObj;
+ struct gl_memory_object *memObj;
+
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_memory_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ texObj = _mesa_lookup_texture(ctx, texture);
+ if (!texObj)
+ return;
+
+ memObj = lookup_memory_object_err(ctx, memory, func);
+ if (!memObj)
+ return;
+
+ _mesa_texture_storage_ms_memory(ctx, dims, texObj, memObj, texObj->Target,
+ samples, internalFormat, width, height,
+ depth, fixedSampleLocations, offset, func);
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texstorage_memory(2, target, levels, internalFormat, width, height, 1,
+ memory, offset, "glTexStorageMem2DEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texstorage_memory_ms(2, target, samples, internalFormat, width, height, 1,
+ fixedSampleLocations, memory, offset,
+ "glTexStorageMem2DMultisampleEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texstorage_memory(3, target, levels, internalFormat, width, height, depth,
+ memory, offset, "glTexStorageMem3DEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texstorage_memory_ms(3, target, samples, internalFormat, width, height,
+ depth, fixedSampleLocations, memory, offset,
+ "glTexStorageMem3DMultisampleEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texturestorage_memory(2, texture, levels, internalFormat, width, height, 1,
+ memory, offset, "glTexureStorageMem2DEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texturestorage_memory_ms(2, texture, samples, internalFormat, width, height,
+ 1, fixedSampleLocations, memory, offset,
+ "glTextureStorageMem2DMultisampleEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texturestorage_memory(3, texture, levels, internalFormat, width, height,
+ depth, memory, offset, "glTextureStorageMem3DEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texturestorage_memory_ms(3, texture, samples, internalFormat, width, height,
+ depth, fixedSampleLocations, memory, offset,
+ "glTextureStorageMem3DMultisampleEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
-
+ texstorage_memory(1, target, levels, internalFormat, width, 1, 1, memory,
+ offset, "glTexStorageMem1DEXT");
}
void GLAPIENTRY
GLuint memory,
GLuint64 offset)
{
+ texturestorage_memory(1, texture, levels, internalFormat, width, 1, 1,
+ memory, offset, "glTextureStorageMem1DEXT");
+}
+
+/**
+ * Used as a placeholder for semaphore objects between glGenSemaphoresEXT()
+ * and glImportSemaphoreFdEXT(), so that glIsSemaphoreEXT() can work correctly.
+ */
+static struct gl_semaphore_object DummySemaphoreObject;
+/**
+ * Delete a semaphore object. Called via ctx->Driver.DeleteSemaphore().
+ * Not removed from hash table here.
+ */
+void
+_mesa_delete_semaphore_object(struct gl_context *ctx,
+ struct gl_semaphore_object *semObj)
+{
+ if (semObj != &DummySemaphoreObject)
+ free(semObj);
+}
+
+/**
+ * Initialize a semaphore object to default values.
+ */
+void
+_mesa_initialize_semaphore_object(struct gl_context *ctx,
+ struct gl_semaphore_object *obj,
+ GLuint name)
+{
+ memset(obj, 0, sizeof(struct gl_semaphore_object));
+ obj->Name = name;
}
void GLAPIENTRY
_mesa_GenSemaphoresEXT(GLsizei n, GLuint *semaphores)
{
+ GET_CURRENT_CONTEXT(ctx);
+
+ const char *func = "glGenSemaphoresEXT";
+ if (MESA_VERBOSE & (VERBOSE_API))
+ _mesa_debug(ctx, "%s(%d, %p)", func, n, semaphores);
+
+ if (!ctx->Extensions.EXT_semaphore) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
+ return;
+ }
+
+ if (!semaphores)
+ return;
+
+ _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects);
+ GLuint first = _mesa_HashFindFreeKeyBlock(ctx->Shared->SemaphoreObjects, n);
+ if (first) {
+ for (GLsizei i = 0; i < n; i++) {
+ semaphores[i] = first + i;
+ _mesa_HashInsertLocked(ctx->Shared->SemaphoreObjects,
+ semaphores[i], &DummySemaphoreObject);
+ }
+ }
+
+ _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects);
}
void GLAPIENTRY
_mesa_DeleteSemaphoresEXT(GLsizei n, const GLuint *semaphores)
{
+ GET_CURRENT_CONTEXT(ctx);
+
+ const char *func = "glDeleteSemaphoresEXT";
+
+ if (MESA_VERBOSE & (VERBOSE_API)) {
+ _mesa_debug(ctx, "%s(%d, %p)\n", func, n, semaphores);
+ }
+
+ if (!ctx->Extensions.EXT_semaphore) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+ if (n < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "%s(n < 0)", func);
+ return;
+ }
+
+ if (!semaphores)
+ return;
+
+ _mesa_HashLockMutex(ctx->Shared->SemaphoreObjects);
+ for (GLint i = 0; i < n; i++) {
+ if (semaphores[i] > 0) {
+ struct gl_semaphore_object *delObj
+ = _mesa_lookup_semaphore_object_locked(ctx, semaphores[i]);
+
+ if (delObj) {
+ _mesa_HashRemoveLocked(ctx->Shared->SemaphoreObjects,
+ semaphores[i]);
+ ctx->Driver.DeleteSemaphoreObject(ctx, delObj);
+ }
+ }
+ }
+ _mesa_HashUnlockMutex(ctx->Shared->SemaphoreObjects);
}
GLboolean GLAPIENTRY
_mesa_IsSemaphoreEXT(GLuint semaphore)
{
- return GL_FALSE;
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_semaphore) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glIsSemaphoreEXT(unsupported)");
+ return GL_FALSE;
+ }
+
+ struct gl_semaphore_object *obj =
+ _mesa_lookup_semaphore_object(ctx, semaphore);
+
+ return obj ? GL_TRUE : GL_FALSE;
+}
+
+/**
+ * Helper that outputs the correct error status for parameter
+ * calls where no pnames are defined
+ */
+static void
+semaphore_parameter_stub(const char* func, GLenum pname)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.EXT_semaphore) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ /* EXT_semaphore and EXT_semaphore_fd define no parameters */
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(pname=0x%x)", func, pname);
}
void GLAPIENTRY
GLenum pname,
const GLuint64 *params)
{
+ const char *func = "glSemaphoreParameterui64vEXT";
+ semaphore_parameter_stub(func, pname);
}
void GLAPIENTRY
GLenum pname,
GLuint64 *params)
{
+ const char *func = "glGetSemaphoreParameterui64vEXT";
+ semaphore_parameter_stub(func, pname);
}
void GLAPIENTRY
const GLuint *textures,
const GLenum *srcLayouts)
{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_semaphore_object *semObj = NULL;
+ struct gl_buffer_object **bufObjs = NULL;
+ struct gl_texture_object **texObjs = NULL;
+
+ const char *func = "glWaitSemaphoreEXT";
+
+ if (!ctx->Extensions.EXT_semaphore) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ semObj = _mesa_lookup_semaphore_object(ctx, semaphore);
+ if (!semObj)
+ return;
+
+ FLUSH_VERTICES(ctx, 0);
+
+ bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers);
+ if (!bufObjs) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)",
+ func, numBufferBarriers);
+ goto end;
+ }
+ for (unsigned i = 0; i < numBufferBarriers; i++) {
+ bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]);
+ }
+
+ texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers);
+ if (!texObjs) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)",
+ func, numTextureBarriers);
+ goto end;
+ }
+
+ for (unsigned i = 0; i < numTextureBarriers; i++) {
+ texObjs[i] = _mesa_lookup_texture(ctx, textures[i]);
+ }
+
+ ctx->Driver.ServerWaitSemaphoreObject(ctx, semObj,
+ numBufferBarriers, bufObjs,
+ numTextureBarriers, texObjs,
+ srcLayouts);
+
+end:
+ free(bufObjs);
+ free(texObjs);
}
void GLAPIENTRY
const GLuint *textures,
const GLenum *dstLayouts)
{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_semaphore_object *semObj = NULL;
+ struct gl_buffer_object **bufObjs = NULL;
+ struct gl_texture_object **texObjs = NULL;
+
+ const char *func = "glSignalSemaphoreEXT";
+
+ if (!ctx->Extensions.EXT_semaphore) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+ semObj = _mesa_lookup_semaphore_object(ctx, semaphore);
+ if (!semObj)
+ return;
+
+ FLUSH_VERTICES(ctx, 0);
+
+ bufObjs = malloc(sizeof(struct gl_buffer_object *) * numBufferBarriers);
+ if (!bufObjs) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numBufferBarriers=%u)",
+ func, numBufferBarriers);
+ goto end;
+ }
+
+ for (unsigned i = 0; i < numBufferBarriers; i++) {
+ bufObjs[i] = _mesa_lookup_bufferobj(ctx, buffers[i]);
+ }
+
+ texObjs = malloc(sizeof(struct gl_texture_object *) * numTextureBarriers);
+ if (!texObjs) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(numTextureBarriers=%u)",
+ func, numTextureBarriers);
+ goto end;
+ }
+ for (unsigned i = 0; i < numTextureBarriers; i++) {
+ texObjs[i] = _mesa_lookup_texture(ctx, textures[i]);
+ }
+
+ ctx->Driver.ServerSignalSemaphoreObject(ctx, semObj,
+ numBufferBarriers, bufObjs,
+ numTextureBarriers, texObjs,
+ dstLayouts);
+
+end:
+ free(bufObjs);
+ free(texObjs);
}
void GLAPIENTRY
{
GET_CURRENT_CONTEXT(ctx);
+ const char *func = "glImportMemoryFdEXT";
+
+ if (!ctx->Extensions.EXT_memory_object_fd) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glImportMemoryFdEXT(handleType=%u)",
- handleType);
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
return;
}
GLenum handleType,
GLint fd)
{
+ GET_CURRENT_CONTEXT(ctx);
+
+ const char *func = "glImportSemaphoreFdEXT";
+
+ if (!ctx->Extensions.EXT_semaphore_fd) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
+ return;
+ }
+
+ if (handleType != GL_HANDLE_TYPE_OPAQUE_FD_EXT) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "%s(handleType=%u)", func, handleType);
+ return;
+ }
+
+ struct gl_semaphore_object *semObj = _mesa_lookup_semaphore_object(ctx,
+ semaphore);
+ if (!semObj)
+ return;
+
+ if (semObj == &DummySemaphoreObject) {
+ semObj = ctx->Driver.NewSemaphoreObject(ctx, semaphore);
+ if (!semObj) {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
+ return;
+ }
+ _mesa_HashInsert(ctx->Shared->SemaphoreObjects, semaphore, semObj);
+ }
+ ctx->Driver.ImportSemaphoreFd(ctx, semObj, fd);
}