|
Packit |
5af8b3 |
/*
|
|
Packit |
5af8b3 |
* Copyright (c) 2016, NVIDIA CORPORATION.
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
Packit |
5af8b3 |
* copy of this software and/or associated documentation files (the
|
|
Packit |
5af8b3 |
* "Materials"), to deal in the Materials without restriction, including
|
|
Packit |
5af8b3 |
* without limitation the rights to use, copy, modify, merge, publish,
|
|
Packit |
5af8b3 |
* distribute, sublicense, and/or sell copies of the Materials, and to
|
|
Packit |
5af8b3 |
* permit persons to whom the Materials are furnished to do so, subject to
|
|
Packit |
5af8b3 |
* the following conditions:
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* The above copyright notice and this permission notice shall be included
|
|
Packit |
5af8b3 |
* unaltered in all copies or substantial portions of the Materials.
|
|
Packit |
5af8b3 |
* Any additions, deletions, or changes to the original source files
|
|
Packit |
5af8b3 |
* must be clearly indicated in accompanying documentation.
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* If only executable code is distributed, then the accompanying
|
|
Packit |
5af8b3 |
* documentation must state that "this software is based in part on the
|
|
Packit |
5af8b3 |
* work of the Khronos Group."
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
5af8b3 |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
5af8b3 |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
Packit |
5af8b3 |
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
Packit |
5af8b3 |
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
Packit |
5af8b3 |
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
Packit |
5af8b3 |
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
Packit |
5af8b3 |
*/
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
#include <EGL/egl.h>
|
|
Packit |
5af8b3 |
#include <EGL/eglext.h>
|
|
Packit |
5af8b3 |
#include <GL/gl.h>
|
|
Packit |
5af8b3 |
#include <stdio.h>
|
|
Packit |
5af8b3 |
#include <stdlib.h>
|
|
Packit |
5af8b3 |
#include <string.h>
|
|
Packit |
5af8b3 |
#include <assert.h>
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
#include "dummy/EGL_dummy.h"
|
|
Packit |
5af8b3 |
#include "egl_test_utils.h"
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
/**
|
|
Packit |
5af8b3 |
* \file
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* Tests for EGL_KHR_debug.
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* This test works by recording the parameters that we expect the debug
|
|
Packit |
5af8b3 |
* callback function to get, and then calling an EGL function that generates an
|
|
Packit |
5af8b3 |
* error.
|
|
Packit |
5af8b3 |
*
|
|
Packit |
5af8b3 |
* The debug callback checks its parameters against the expected values, and
|
|
Packit |
5af8b3 |
* exits if any of them don't match.
|
|
Packit |
5af8b3 |
*/
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
static const EGLLabelKHR THREAD_LABEL = (EGLLabelKHR) "THREAD_LABEL";
|
|
Packit |
5af8b3 |
static const EGLLabelKHR DISPLAY_LABEL = (EGLLabelKHR) "DISPLAY_LABEL";
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
static void testCallback(EGLDisplay dpy, EGLBoolean callbackEnabled);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
static void EGLAPIENTRY debugCallback(EGLenum error, const char *command,
|
|
Packit |
5af8b3 |
EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel,
|
|
Packit |
5af8b3 |
const char *message);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
/**
|
|
Packit |
5af8b3 |
* Records the expected parameters for the next call to the debug callback.
|
|
Packit |
5af8b3 |
*/
|
|
Packit |
5af8b3 |
static void setCallbackExpected(const char *command, EGLenum error,
|
|
Packit |
5af8b3 |
EGLLabelKHR objectLabel, const char *message);
|
|
Packit |
5af8b3 |
static void setCallbackNotExpected(void);
|
|
Packit |
5af8b3 |
static void checkError(EGLint expectedError);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
/**
|
|
Packit |
5af8b3 |
* True if the debug callback has been called since the last call to
|
|
Packit |
5af8b3 |
* \c setCallbackExpected. This is used to make sure that the debug callback
|
|
Packit |
5af8b3 |
* is called exactly once when a function generates an error.
|
|
Packit |
5af8b3 |
*/
|
|
Packit |
5af8b3 |
static EGLBoolean callbackWasCalled = EGL_FALSE;
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// These are the expected values for the next call to the debug callback, set
|
|
Packit |
5af8b3 |
// from setCallbackExpected and setCallbackNotExpected.
|
|
Packit |
5af8b3 |
static EGLBoolean shouldExpectCallback = EGL_FALSE;
|
|
Packit |
5af8b3 |
static const char *nextExpectedCommand = NULL;
|
|
Packit |
5af8b3 |
static EGLint nextExpectedError = EGL_NONE;
|
|
Packit |
5af8b3 |
static EGLLabelKHR nextExpectedObject = NULL;
|
|
Packit |
5af8b3 |
static const char *nextExpectedMessage = NULL;
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
int main(int argc, char **argv)
|
|
Packit |
5af8b3 |
{
|
|
Packit |
5af8b3 |
EGLDisplay dpy;
|
|
Packit |
5af8b3 |
EGLAttrib callbackAttribs[] = {
|
|
Packit |
5af8b3 |
EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE,
|
|
Packit |
5af8b3 |
EGL_NONE
|
|
Packit |
5af8b3 |
};
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// We shouldn't get a callback for anything yet.
|
|
Packit |
5af8b3 |
setCallbackNotExpected();
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
loadEGLExtensions();
|
|
Packit |
5af8b3 |
dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
Packit |
5af8b3 |
checkError(EGL_SUCCESS);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
ptr_eglLabelObjectKHR(EGL_NO_DISPLAY, EGL_OBJECT_THREAD_KHR, NULL, THREAD_LABEL);
|
|
Packit |
5af8b3 |
ptr_eglLabelObjectKHR(dpy, EGL_OBJECT_DISPLAY_KHR, (EGLObjectKHR) dpy, DISPLAY_LABEL);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Start by enabling the callback and generating some EGL errors. Make sure
|
|
Packit |
5af8b3 |
// that the callback gets called with the correct parameters.
|
|
Packit |
5af8b3 |
printf("Testing with callback\n");
|
|
Packit |
5af8b3 |
ptr_eglDebugMessageControlKHR(debugCallback, NULL);
|
|
Packit |
5af8b3 |
testCallback(dpy, EGL_TRUE);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Disable the callback and try again. This time, the callback should not
|
|
Packit |
5af8b3 |
// be called, but we should still get the same errors from eglGetError.
|
|
Packit |
5af8b3 |
printf("Testing with no callback\n");
|
|
Packit |
5af8b3 |
ptr_eglDebugMessageControlKHR(NULL, NULL);
|
|
Packit |
5af8b3 |
testCallback(dpy, EGL_FALSE);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Set a callback, but disable error messages. Again, the callback should
|
|
Packit |
5af8b3 |
// not be called.
|
|
Packit |
5af8b3 |
printf("Testing with callback and error messages disabled\n");
|
|
Packit |
5af8b3 |
callbackAttribs[1] = EGL_FALSE;
|
|
Packit |
5af8b3 |
ptr_eglDebugMessageControlKHR(debugCallback, callbackAttribs);
|
|
Packit |
5af8b3 |
testCallback(dpy, EGL_FALSE);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
return 0;
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
void testCallback(EGLDisplay dpy, EGLBoolean callbackEnabled)
|
|
Packit |
5af8b3 |
{
|
|
Packit |
5af8b3 |
static const EGLint ERROR_ATTRIBS[] = {
|
|
Packit |
5af8b3 |
EGL_CREATE_CONTEXT_FAIL, EGL_BAD_MATCH,
|
|
Packit |
5af8b3 |
EGL_NONE
|
|
Packit |
5af8b3 |
};
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (!callbackEnabled) {
|
|
Packit |
5af8b3 |
setCallbackNotExpected();
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Generate an error from libEGL.so.
|
|
Packit |
5af8b3 |
printf("Checking eglGetCurrentSurface\n");
|
|
Packit |
5af8b3 |
if (callbackEnabled) {
|
|
Packit |
5af8b3 |
setCallbackExpected("eglGetCurrentSurface", EGL_BAD_PARAMETER,
|
|
Packit |
5af8b3 |
THREAD_LABEL, NULL);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
eglGetCurrentSurface(EGL_NONE);
|
|
Packit |
5af8b3 |
checkError(EGL_BAD_PARAMETER);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Generate an error from a dispatch stub that expects a display. This
|
|
Packit |
5af8b3 |
// should go through the same error reporting as eglGetCurrentSurface did.
|
|
Packit |
5af8b3 |
printf("Checking eglCreateContext with invalid display\n");
|
|
Packit |
5af8b3 |
if (callbackEnabled) {
|
|
Packit |
5af8b3 |
setCallbackExpected("eglCreateContext", EGL_BAD_DISPLAY,
|
|
Packit |
5af8b3 |
NULL, NULL);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
eglCreateContext(EGL_NO_DISPLAY, NULL, EGL_NO_CONTEXT, NULL);
|
|
Packit |
5af8b3 |
checkError(EGL_BAD_DISPLAY);
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Generate an error from the vendor library, to make sure that all of the
|
|
Packit |
5af8b3 |
// EGL_KHR_debug calls got passed through correctly. The vendor library
|
|
Packit |
5af8b3 |
// should pass the display label to the callback, and it uses the vendor
|
|
Packit |
5af8b3 |
// name as the message.
|
|
Packit |
5af8b3 |
printf("Checking eglCreateContext with valid display\n");
|
|
Packit |
5af8b3 |
if (callbackEnabled) {
|
|
Packit |
5af8b3 |
setCallbackExpected("eglCreateContext", EGL_BAD_MATCH,
|
|
Packit |
5af8b3 |
DISPLAY_LABEL, DUMMY_VENDOR_NAMES[0]);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
eglCreateContext(dpy, NULL, EGL_NO_CONTEXT, ERROR_ATTRIBS);
|
|
Packit |
5af8b3 |
checkError(EGL_BAD_MATCH);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
void setCallbackExpected(const char *command, EGLenum error,
|
|
Packit |
5af8b3 |
EGLLabelKHR objectLabel, const char *message)
|
|
Packit |
5af8b3 |
{
|
|
Packit |
5af8b3 |
shouldExpectCallback = EGL_TRUE;
|
|
Packit |
5af8b3 |
nextExpectedCommand = command;
|
|
Packit |
5af8b3 |
nextExpectedError = error;
|
|
Packit |
5af8b3 |
nextExpectedObject = objectLabel;
|
|
Packit |
5af8b3 |
nextExpectedMessage = message;
|
|
Packit |
5af8b3 |
callbackWasCalled = EGL_FALSE;
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
void setCallbackNotExpected(void)
|
|
Packit |
5af8b3 |
{
|
|
Packit |
5af8b3 |
shouldExpectCallback = EGL_FALSE;
|
|
Packit |
5af8b3 |
callbackWasCalled = EGL_FALSE;
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
void EGLAPIENTRY debugCallback(EGLenum error, const char *command,
|
|
Packit |
5af8b3 |
EGLint messageType, EGLLabelKHR threadLabel, EGLLabelKHR objectLabel,
|
|
Packit |
5af8b3 |
const char *message)
|
|
Packit |
5af8b3 |
{
|
|
Packit |
5af8b3 |
// First, make sure the debug callback was supposed to be called at all.
|
|
Packit |
5af8b3 |
if (!shouldExpectCallback) {
|
|
Packit |
5af8b3 |
printf("Unexpected callback from \"%s\"\n", command);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Make sure the callback only gets called once.
|
|
Packit |
5af8b3 |
if (callbackWasCalled) {
|
|
Packit |
5af8b3 |
printf("Callback called multiple times from \"%s\"\n", command);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
callbackWasCalled = EGL_TRUE;
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (messageType != EGL_DEBUG_MSG_ERROR_KHR) {
|
|
Packit |
5af8b3 |
printf("Unexpected callback type: Expected 0x%04x, got 0x%04x\n",
|
|
Packit |
5af8b3 |
EGL_DEBUG_MSG_ERROR_KHR, messageType);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (error != nextExpectedError) {
|
|
Packit |
5af8b3 |
printf("Unexpected callback error: Expected 0x%04x, got 0x%04x\n",
|
|
Packit |
5af8b3 |
nextExpectedError, error);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (command == NULL) {
|
|
Packit |
5af8b3 |
printf("Command is NULL\n");
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (nextExpectedCommand != NULL) {
|
|
Packit |
5af8b3 |
if (strcmp(nextExpectedCommand, command) != 0) {
|
|
Packit |
5af8b3 |
printf("Unexpected command: Expected \"%s\", got \"%s\"\n",
|
|
Packit |
5af8b3 |
nextExpectedCommand, command);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (nextExpectedMessage != NULL) {
|
|
Packit |
5af8b3 |
if (message != NULL) {
|
|
Packit |
5af8b3 |
if (strcmp(nextExpectedMessage, message) != 0) {
|
|
Packit |
5af8b3 |
printf("Unexpected message: Expected \"%s\", got \"%s\"\n",
|
|
Packit |
5af8b3 |
nextExpectedMessage, message);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
} else {
|
|
Packit |
5af8b3 |
printf("Message is NULL, but should be \"%s\"\n", nextExpectedMessage);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (threadLabel != THREAD_LABEL) {
|
|
Packit |
5af8b3 |
printf("Unexpected thread label: Expected %p, got %p\n",
|
|
Packit |
5af8b3 |
THREAD_LABEL, threadLabel);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
if (objectLabel != nextExpectedObject) {
|
|
Packit |
5af8b3 |
printf("Unexpected object label: Expected %p, got %p\n",
|
|
Packit |
5af8b3 |
nextExpectedObject, objectLabel);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
void checkError(EGLint expectedError)
|
|
Packit |
5af8b3 |
{
|
|
Packit |
5af8b3 |
EGLint error;
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// If we expected a callback, then make sure we got one.
|
|
Packit |
5af8b3 |
if (shouldExpectCallback) {
|
|
Packit |
5af8b3 |
if (!callbackWasCalled) {
|
|
Packit |
5af8b3 |
printf("Callback was not called\n");
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Nothing else should call the callback now.
|
|
Packit |
5af8b3 |
setCallbackNotExpected();
|
|
Packit |
5af8b3 |
|
|
Packit |
5af8b3 |
// Regardless of whether we expected a callback, make sure we get the
|
|
Packit |
5af8b3 |
// correct error code.
|
|
Packit |
5af8b3 |
error = eglGetError();
|
|
Packit |
5af8b3 |
if (error != expectedError) {
|
|
Packit |
5af8b3 |
printf("Got wrong error: Expected 0x%04x, got 0x%04x\n", expectedError, error);
|
|
Packit |
5af8b3 |
exit(1);
|
|
Packit |
5af8b3 |
}
|
|
Packit |
5af8b3 |
}
|