Blame tests/testegldebug.c

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