summaryrefslogtreecommitdiff
path: root/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c')
-rw-r--r--drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c1306
1 files changed, 1306 insertions, 0 deletions
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c
new file mode 100644
index 000000000000..8b0289705ab0
--- /dev/null
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_debug.c
@@ -0,0 +1,1306 @@
+/****************************************************************************
+*
+* The MIT License (MIT)
+*
+* Copyright (c) 2014 - 2020 Vivante Corporation
+*
+* Permission is hereby granted, free of charge, to any person obtaining a
+* copy of this software and associated documentation files (the "Software"),
+* to deal in the Software without restriction, including without limitation
+* the rights to use, copy, modify, merge, publish, distribute, sublicense,
+* and/or sell copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+* DEALINGS IN THE SOFTWARE.
+*
+*****************************************************************************
+*
+* The GPL License (GPL)
+*
+* Copyright (C) 2014 - 2020 Vivante Corporation
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*****************************************************************************
+*
+* Note: This software is released under dual MIT and GPL licenses. A
+* recipient may use this file under the terms of either the MIT license or
+* GPL License. If you wish to use only one license not the other, you can
+* indicate your decision by deleting one of the above license notices in your
+* version of this file.
+*
+*****************************************************************************/
+
+
+#include "gc_hal_kernel_precomp.h"
+#include <gc_hal_kernel_debug.h>
+
+/******************************************************************************\
+******************************** Debug Variables *******************************
+\******************************************************************************/
+
+static gceSTATUS _lastError = gcvSTATUS_OK;
+static gctUINT32 _debugLevel = gcvLEVEL_ERROR;
+/*
+_debugZones config value
+Please Reference define in gc_hal_base.h
+*/
+static gctUINT32 _debugZones = gcdZONE_NONE;
+
+/******************************************************************************\
+********************************* Debug Switches *******************************
+\******************************************************************************/
+
+/*
+ gcdTHREAD_BUFFERS
+
+ When greater then one, will accumulate messages from the specified number
+ of threads in separate output buffers.
+*/
+#define gcdTHREAD_BUFFERS 1
+
+/*
+ gcdSHOW_LINE_NUMBER
+
+ When enabledm each print statement will be preceeded with the current
+ line number.
+*/
+#define gcdSHOW_LINE_NUMBER 0
+
+/*
+ gcdSHOW_PROCESS_ID
+
+ When enabledm each print statement will be preceeded with the current
+ process ID.
+*/
+#define gcdSHOW_PROCESS_ID 0
+
+/*
+ gcdSHOW_THREAD_ID
+
+ When enabledm each print statement will be preceeded with the current
+ thread ID.
+*/
+#define gcdSHOW_THREAD_ID 0
+
+/*
+ gcdSHOW_TIME
+
+ When enabled each print statement will be preceeded with the current
+ high-resolution time.
+*/
+#define gcdSHOW_TIME 0
+
+
+/******************************************************************************\
+****************************** Miscellaneous Macros ****************************
+\******************************************************************************/
+
+#if gcdSHOW_TIME || gcdSHOW_LINE_NUMBER || gcdSHOW_PROCESS_ID || gcdSHOW_THREAD_ID
+# define gcdHAVEPREFIX 1
+#else
+# define gcdHAVEPREFIX 0
+#endif
+
+/******************************************************************************\
+****************************** Private Structures ******************************
+\******************************************************************************/
+
+typedef struct _gcsBUFFERED_OUTPUT * gcsBUFFERED_OUTPUT_PTR;
+typedef struct _gcsBUFFERED_OUTPUT
+{
+#if gcdTHREAD_BUFFERS > 1
+ gctUINT32 threadID;
+#endif
+
+#if gcdSHOW_LINE_NUMBER
+ gctUINT lineNumber;
+#endif
+
+ gctINT indent;
+
+ gcsBUFFERED_OUTPUT_PTR prev;
+ gcsBUFFERED_OUTPUT_PTR next;
+}
+gcsBUFFERED_OUTPUT;
+
+static gcsBUFFERED_OUTPUT _outputBuffer[gcdTHREAD_BUFFERS];
+static gcsBUFFERED_OUTPUT_PTR _outputBufferHead = gcvNULL;
+static gcsBUFFERED_OUTPUT_PTR _outputBufferTail = gcvNULL;
+
+/******************************************************************************\
+******************************* Printing Functions *****************************
+\******************************************************************************/
+
+#if gcdHAVEPREFIX
+
+#if gcdSHOW_TIME
+static gcmINLINE gctUINT64
+_GetTime(
+ void
+ )
+{
+ gctUINT64 time;
+ gckOS_GetProfileTick(&time);
+ return time;
+}
+# define gcdPREFIX_LEADER 1
+# define gcdTIMEFORMAT "%18lld"
+# define gcdTIMEVALUE ,_GetTime()
+# else
+# define gcdTIMEFORMAT
+# define gcdTIMEVALUE
+# endif
+
+#if gcdSHOW_LINE_NUMBER
+#ifndef gcdPREFIX_LEADER
+# define gcdPREFIX_LEADER 1
+# define gcdNUMFORMAT "%8u"
+# else
+# define gcdNUMFORMAT ", %8u"
+# endif
+# define gcdNUMVALUE ,OutputBuffer->lineNumber
+# else
+# define gcdNUMFORMAT
+# define gcdNUMVALUE
+# endif
+
+#if gcdSHOW_PROCESS_ID
+#ifndef gcdPREFIX_LEADER
+# define gcdPREFIX_LEADER 1
+# define gcdPIDFORMAT "pid=%5u"
+# else
+# define gcdPIDFORMAT ", pid=%5u"
+# endif
+# define gcdPIDVALUE ,gcmkGETPROCESSID()
+# else
+# define gcdPIDFORMAT
+# define gcdPIDVALUE
+# endif
+
+#if gcdSHOW_THREAD_ID
+#ifndef gcdPREFIX_LEADER
+# define gcdPREFIX_LEADER 1
+# define gcdTIDFORMAT "tid=%5u"
+# else
+# define gcdTIDFORMAT ", tid=%5u"
+# endif
+# define gcdTIDVALUE ,gcmkGETTHREADID()
+# else
+# define gcdTIDFORMAT
+# define gcdTIDVALUE
+# endif
+
+static gctUINT
+_PrintPrefix(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN char Buffer[],
+ IN gctUINT Size
+ )
+{
+ gctINT len;
+
+ /* Format the string. */
+ len = gcmkSPRINTF(Buffer,
+ Size,
+ "[" gcdTIMEFORMAT gcdNUMFORMAT gcdPIDFORMAT gcdTIDFORMAT "] "
+ gcdTIMEVALUE gcdNUMVALUE gcdPIDVALUE gcdTIDVALUE);
+
+ if (len > 0)
+ {
+ Buffer[len] = '\0';
+ return (gctUINT)len;
+ }
+
+ return 0;
+}
+#endif
+
+static int
+_AppendIndent(
+ IN gctINT Indent,
+ IN char * Buffer,
+ IN int BufferSize
+ )
+{
+ gctINT i;
+
+ gctINT len = 0;
+ gctINT indent = Indent % 40;
+
+ for (i = 0; i < indent; i += 1)
+ {
+ Buffer[len++] = ' ';
+ }
+
+ if (indent != Indent)
+ {
+ len += gcmkSPRINTF(
+ Buffer + len, BufferSize - len, " <%d> ", Indent
+ );
+
+ Buffer[len] = '\0';
+ }
+
+ return len;
+}
+
+static gctUINT
+_PrintString(
+ IN gcsBUFFERED_OUTPUT_PTR OutputBuffer,
+ IN gctINT Indent,
+ IN gctCONST_STRING Message,
+ IN gctPOINTER Data,
+ IN char Buffer[],
+ IN gctUINT Size
+ )
+{
+ gctINT len;
+
+ /* Append the indent string. */
+ len = _AppendIndent(Indent, Buffer, Size);
+
+ /* Format the string. */
+ len += gcmkVSPRINTF(Buffer + len, Size - len, Message, Data);
+ Buffer[len] = '\0';
+
+ /* Add end-of-line if missing. */
+ if (Buffer[len - 1] != '\n')
+ {
+ Buffer[len++] = '\n';
+ Buffer[len] = '\0';
+ }
+
+ return (gctUINT)len;
+}
+
+/******************************************************************************\
+******************************* Private Functions ******************************
+\******************************************************************************/
+
+static gcmINLINE void
+_InitBuffers(
+ void
+ )
+{
+ int i;
+
+ if (_outputBufferHead == gcvNULL)
+ {
+ for (i = 0; i < gcdTHREAD_BUFFERS; i += 1)
+ {
+ if (_outputBufferTail == gcvNULL)
+ {
+ _outputBufferHead = &_outputBuffer[i];
+ }
+ else
+ {
+ _outputBufferTail->next = &_outputBuffer[i];
+ }
+
+#if gcdTHREAD_BUFFERS > 1
+ _outputBuffer[i].threadID = ~0U;
+#endif
+
+ _outputBuffer[i].prev = _outputBufferTail;
+ _outputBuffer[i].next = gcvNULL;
+
+ _outputBufferTail = &_outputBuffer[i];
+ }
+ }
+}
+
+static gcmINLINE gcsBUFFERED_OUTPUT_PTR
+_GetOutputBuffer(
+ void
+ )
+{
+ gcsBUFFERED_OUTPUT_PTR outputBuffer;
+
+#if gcdTHREAD_BUFFERS > 1
+ /* Get the current thread ID. */
+ gctUINT32 ThreadID = gcmkGETTHREADID();
+
+ /* Locate the output buffer for the thread. */
+ outputBuffer = _outputBufferHead;
+
+ while (outputBuffer != gcvNULL)
+ {
+ if (outputBuffer->threadID == ThreadID)
+ {
+ break;
+ }
+
+ outputBuffer = outputBuffer->next;
+ }
+
+ /* No matching buffer found? */
+ if (outputBuffer == gcvNULL)
+ {
+ /* Get the tail for the buffer. */
+ outputBuffer = _outputBufferTail;
+
+ /* Move it to the head. */
+ _outputBufferTail = _outputBufferTail->prev;
+ _outputBufferTail->next = gcvNULL;
+
+ outputBuffer->prev = gcvNULL;
+ outputBuffer->next = _outputBufferHead;
+
+ _outputBufferHead->prev = outputBuffer;
+ _outputBufferHead = outputBuffer;
+
+ /* Reset the buffer. */
+ outputBuffer->threadID = ThreadID;
+#if gcdSHOW_LINE_NUMBER
+ outputBuffer->lineNumber = 0;
+# endif
+ }
+#else
+ outputBuffer = _outputBufferHead;
+#endif
+
+ return outputBuffer;
+}
+
+static void
+_Print(
+ IN gctCONST_STRING Message,
+ IN gctARGUMENTS * Arguments
+ )
+{
+ gcsBUFFERED_OUTPUT_PTR outputBuffer;
+ char buffer[256];
+ char *ptr = buffer;
+ gctINT len = 0;
+ static gcmkDECLARE_MUTEX(printMutex);
+
+ gcmkMUTEX_LOCK(printMutex);
+
+ /* Initialize output buffer list. */
+ _InitBuffers();
+
+ /* Locate the proper output buffer. */
+ outputBuffer = _GetOutputBuffer();
+
+ /* Print prefix. */
+#if gcdHAVEPREFIX
+#if gcdSHOW_LINE_NUMBER
+ /* Update the line number. */
+ outputBuffer->lineNumber += 1;
+# endif
+
+ /* Print the prefix. */
+ len = _PrintPrefix(outputBuffer, buffer, gcmSIZEOF(buffer));
+ ptr += len;
+#endif
+
+ /* Form the indent string. */
+ if (Message[0] == '-' && Message[1] == '-')
+ {
+ outputBuffer->indent -= 2;
+ }
+
+ /* Print the message. */
+ len += _PrintString(
+ outputBuffer, outputBuffer->indent,
+ Message, ((gctPOINTER) Arguments),
+ ptr, gcmSIZEOF(buffer) - outputBuffer->indent - len
+ );
+
+ gcmkOUTPUT_STRING(buffer);
+
+ /* Check increasing indent. */
+ if (Message[0] == '+' && Message[1] == '+')
+ {
+ outputBuffer->indent += 2;
+ }
+
+ gcmkMUTEX_UNLOCK(printMutex);
+}
+
+
+/******************************************************************************\
+********************************* Debug Macros *********************************
+\******************************************************************************/
+
+#ifdef __QNXNTO__
+
+extern volatile unsigned g_nQnxInIsrs;
+
+#define gcmDEBUGPRINT(Message) \
+{ \
+ if (atomic_add_value(&g_nQnxInIsrs, 1) == 0) \
+ { \
+ gctARGUMENTS __arguments__; \
+ gcmkARGUMENTS_START(__arguments__, Message); \
+ _Print(Message, &__arguments__); \
+ gcmkARGUMENTS_END(__arguments__); \
+ } \
+ atomic_sub(&g_nQnxInIsrs, 1); \
+}
+
+#elif defined(__VXWORKS__)
+#define gcmDEBUGPRINT(Message) \
+{ \
+ printf(Message); \
+}
+
+#else
+
+#define gcmDEBUGPRINT(Message) \
+{ \
+ gctARGUMENTS __arguments__; \
+ gcmkARGUMENTS_START(__arguments__, Message); \
+ _Print(Message, &__arguments__); \
+ gcmkARGUMENTS_END(__arguments__); \
+}
+
+#endif
+
+/******************************************************************************\
+********************************** Debug Code **********************************
+\******************************************************************************/
+
+/*******************************************************************************
+**
+** gckOS_Print
+**
+** Send a message to the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Print(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmDEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTrace
+**
+** Send a leveled message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level of message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTrace(
+ IN gctUINT32 Level,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if (Level > _debugLevel)
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugTraceZone
+**
+** Send a leveled and zoned message to the debugger.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** Debug level for message.
+**
+** gctUINT32 Zone
+** Debug zone for message.
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_DebugTraceZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone,
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ if ((Level > _debugLevel) || !(Zone & _debugZones))
+ {
+ return;
+ }
+
+ gcmDEBUGPRINT(Message);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugBreak
+**
+** Break into the debugger.
+**
+** INPUT:
+**
+** Nothing.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugBreak(
+ void
+ )
+{
+ gckOS_DebugTrace(gcvLEVEL_ERROR, "%s(%d)", __FUNCTION__, __LINE__);
+}
+
+/*******************************************************************************
+**
+** gckOS_DebugFatal
+**
+** Send a message to the debugger and break into the debugger.
+**
+** INPUT:
+**
+** gctCONST_STRING Message
+** Pointer to message.
+**
+** ...
+** Optional arguments.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DebugFatal(
+ IN gctCONST_STRING Message,
+ ...
+ )
+{
+ gcmkPRINT_VERSION();
+ gcmDEBUGPRINT(Message);
+
+ /* Break into the debugger. */
+ gckOS_DebugBreak();
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevel
+**
+** Set the debug level.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevel(
+ IN gctUINT32 Level
+ )
+{
+ _debugLevel = Level;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZone
+**
+** Set the debug zone.
+**
+** INPUT:
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_SetDebugZone(
+ IN gctUINT32 Zone
+ )
+{
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugLevelZone
+**
+** Set the debug level and zone.
+**
+** INPUT:
+**
+** gctUINT32 Level
+** New debug level.
+**
+** gctUINT32 Zone
+** New debug zone.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugLevelZone(
+ IN gctUINT32 Level,
+ IN gctUINT32 Zone
+ )
+{
+ _debugLevel = Level;
+ _debugZones = Zone;
+}
+
+/*******************************************************************************
+**
+** gckOS_SetDebugZones
+**
+** Enable or disable debug zones.
+**
+** INPUT:
+**
+** gctUINT32 Zones
+** Debug zones to enable or disable.
+**
+** gctBOOL Enable
+** Set to gcvTRUE to enable the zones (or the Zones with the current
+** zones) or gcvFALSE to disable the specified Zones.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_SetDebugZones(
+ IN gctUINT32 Zones,
+ IN gctBOOL Enable
+ )
+{
+ if (Enable)
+ {
+ /* Enable the zones. */
+ _debugZones |= Zones;
+ }
+ else
+ {
+ /* Disable the zones. */
+ _debugZones &= ~Zones;
+ }
+}
+
+/*******************************************************************************
+**
+** gckOS_Verify
+**
+** Called to verify the result of a function call.
+**
+** INPUT:
+**
+** gceSTATUS Status
+** Function call result.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+
+void
+gckOS_Verify(
+ IN gceSTATUS status
+ )
+{
+ _lastError = status;
+}
+
+gctCONST_STRING
+gckOS_DebugStatus2Name(
+ gceSTATUS status
+ )
+{
+ switch (status)
+ {
+ case gcvSTATUS_OK:
+ return "gcvSTATUS_OK";
+ case gcvSTATUS_TRUE:
+ return "gcvSTATUS_TRUE";
+ case gcvSTATUS_NO_MORE_DATA:
+ return "gcvSTATUS_NO_MORE_DATA";
+ case gcvSTATUS_CACHED:
+ return "gcvSTATUS_CACHED";
+ case gcvSTATUS_MIPMAP_TOO_LARGE:
+ return "gcvSTATUS_MIPMAP_TOO_LARGE";
+ case gcvSTATUS_NAME_NOT_FOUND:
+ return "gcvSTATUS_NAME_NOT_FOUND";
+ case gcvSTATUS_NOT_OUR_INTERRUPT:
+ return "gcvSTATUS_NOT_OUR_INTERRUPT";
+ case gcvSTATUS_MISMATCH:
+ return "gcvSTATUS_MISMATCH";
+ case gcvSTATUS_MIPMAP_TOO_SMALL:
+ return "gcvSTATUS_MIPMAP_TOO_SMALL";
+ case gcvSTATUS_LARGER:
+ return "gcvSTATUS_LARGER";
+ case gcvSTATUS_SMALLER:
+ return "gcvSTATUS_SMALLER";
+ case gcvSTATUS_CHIP_NOT_READY:
+ return "gcvSTATUS_CHIP_NOT_READY";
+ case gcvSTATUS_NEED_CONVERSION:
+ return "gcvSTATUS_NEED_CONVERSION";
+ case gcvSTATUS_SKIP:
+ return "gcvSTATUS_SKIP";
+ case gcvSTATUS_DATA_TOO_LARGE:
+ return "gcvSTATUS_DATA_TOO_LARGE";
+ case gcvSTATUS_INVALID_CONFIG:
+ return "gcvSTATUS_INVALID_CONFIG";
+ case gcvSTATUS_CHANGED:
+ return "gcvSTATUS_CHANGED";
+ case gcvSTATUS_NOT_SUPPORT_DITHER:
+ return "gcvSTATUS_NOT_SUPPORT_DITHER";
+
+ case gcvSTATUS_INVALID_ARGUMENT:
+ return "gcvSTATUS_INVALID_ARGUMENT";
+ case gcvSTATUS_INVALID_OBJECT:
+ return "gcvSTATUS_INVALID_OBJECT";
+ case gcvSTATUS_OUT_OF_MEMORY:
+ return "gcvSTATUS_OUT_OF_MEMORY";
+ case gcvSTATUS_MEMORY_LOCKED:
+ return "gcvSTATUS_MEMORY_LOCKED";
+ case gcvSTATUS_MEMORY_UNLOCKED:
+ return "gcvSTATUS_MEMORY_UNLOCKED";
+ case gcvSTATUS_HEAP_CORRUPTED:
+ return "gcvSTATUS_HEAP_CORRUPTED";
+ case gcvSTATUS_GENERIC_IO:
+ return "gcvSTATUS_GENERIC_IO";
+ case gcvSTATUS_INVALID_ADDRESS:
+ return "gcvSTATUS_INVALID_ADDRESS";
+ case gcvSTATUS_CONTEXT_LOSSED:
+ return "gcvSTATUS_CONTEXT_LOSSED";
+ case gcvSTATUS_TOO_COMPLEX:
+ return "gcvSTATUS_TOO_COMPLEX";
+ case gcvSTATUS_BUFFER_TOO_SMALL:
+ return "gcvSTATUS_BUFFER_TOO_SMALL";
+ case gcvSTATUS_INTERFACE_ERROR:
+ return "gcvSTATUS_INTERFACE_ERROR";
+ case gcvSTATUS_NOT_SUPPORTED:
+ return "gcvSTATUS_NOT_SUPPORTED";
+ case gcvSTATUS_MORE_DATA:
+ return "gcvSTATUS_MORE_DATA";
+ case gcvSTATUS_TIMEOUT:
+ return "gcvSTATUS_TIMEOUT";
+ case gcvSTATUS_OUT_OF_RESOURCES:
+ return "gcvSTATUS_OUT_OF_RESOURCES";
+ case gcvSTATUS_INVALID_DATA:
+ return "gcvSTATUS_INVALID_DATA";
+ case gcvSTATUS_INVALID_MIPMAP:
+ return "gcvSTATUS_INVALID_MIPMAP";
+ case gcvSTATUS_NOT_FOUND:
+ return "gcvSTATUS_NOT_FOUND";
+ case gcvSTATUS_NOT_ALIGNED:
+ return "gcvSTATUS_NOT_ALIGNED";
+ case gcvSTATUS_INVALID_REQUEST:
+ return "gcvSTATUS_INVALID_REQUEST";
+ case gcvSTATUS_GPU_NOT_RESPONDING:
+ return "gcvSTATUS_GPU_NOT_RESPONDING";
+ case gcvSTATUS_TIMER_OVERFLOW:
+ return "gcvSTATUS_TIMER_OVERFLOW";
+ case gcvSTATUS_VERSION_MISMATCH:
+ return "gcvSTATUS_VERSION_MISMATCH";
+ case gcvSTATUS_LOCKED:
+ return "gcvSTATUS_LOCKED";
+ case gcvSTATUS_INTERRUPTED:
+ return "gcvSTATUS_INTERRUPTED";
+ case gcvSTATUS_DEVICE:
+ return "gcvSTATUS_DEVICE";
+ case gcvSTATUS_NOT_MULTI_PIPE_ALIGNED:
+ return "gcvSTATUS_NOT_MULTI_PIPE_ALIGNED";
+
+ /* Linker errors. */
+ case gcvSTATUS_GLOBAL_TYPE_MISMATCH:
+ return "gcvSTATUS_GLOBAL_TYPE_MISMATCH";
+ case gcvSTATUS_TOO_MANY_ATTRIBUTES:
+ return "gcvSTATUS_TOO_MANY_ATTRIBUTES";
+ case gcvSTATUS_TOO_MANY_UNIFORMS:
+ return "gcvSTATUS_TOO_MANY_UNIFORMS";
+ case gcvSTATUS_TOO_MANY_VARYINGS:
+ return "gcvSTATUS_TOO_MANY_VARYINGS";
+ case gcvSTATUS_UNDECLARED_VARYING:
+ return "gcvSTATUS_UNDECLARED_VARYING";
+ case gcvSTATUS_VARYING_TYPE_MISMATCH:
+ return "gcvSTATUS_VARYING_TYPE_MISMATCH";
+ case gcvSTATUS_MISSING_MAIN:
+ return "gcvSTATUS_MISSING_MAIN";
+ case gcvSTATUS_NAME_MISMATCH:
+ return "gcvSTATUS_NAME_MISMATCH";
+ case gcvSTATUS_INVALID_INDEX:
+ return "gcvSTATUS_INVALID_INDEX";
+ case gcvSTATUS_UNIFORM_MISMATCH:
+ return "gcvSTATUS_UNIFORM_MISMATCH";
+ case gcvSTATUS_UNSAT_LIB_SYMBOL:
+ return "gcvSTATUS_UNSAT_LIB_SYMBOL";
+ case gcvSTATUS_TOO_MANY_SHADERS:
+ return "gcvSTATUS_TOO_MANY_SHADERS";
+ case gcvSTATUS_LINK_INVALID_SHADERS:
+ return "gcvSTATUS_LINK_INVALID_SHADERS";
+ case gcvSTATUS_CS_NO_WORKGROUP_SIZE:
+ return "gcvSTATUS_CS_NO_WORKGROUP_SIZE";
+ case gcvSTATUS_LINK_LIB_ERROR:
+ return "gcvSTATUS_LINK_LIB_ERROR";
+ case gcvSTATUS_SHADER_VERSION_MISMATCH:
+ return "gcvSTATUS_SHADER_VERSION_MISMATCH";
+ case gcvSTATUS_TOO_MANY_INSTRUCTION:
+ return "gcvSTATUS_TOO_MANY_INSTRUCTION";
+ case gcvSTATUS_SSBO_MISMATCH:
+ return "gcvSTATUS_SSBO_MISMATCH";
+ case gcvSTATUS_TOO_MANY_OUTPUT:
+ return "gcvSTATUS_TOO_MANY_OUTPUT";
+ case gcvSTATUS_TOO_MANY_INPUT:
+ return "gcvSTATUS_TOO_MANY_INPUT";
+ case gcvSTATUS_NOT_SUPPORT_CL:
+ return "gcvSTATUS_NOT_SUPPORT_CL";
+ case gcvSTATUS_NOT_SUPPORT_INTEGER:
+ return "gcvSTATUS_NOT_SUPPORT_INTEGER";
+ case gcvSTATUS_UNIFORM_TYPE_MISMATCH:
+ return "gcvSTATUS_UNIFORM_TYPE_MISMATCH";
+ case gcvSTATUS_MISSING_PRIMITIVE_TYPE:
+ return "gcvSTATUS_MISSING_PRIMITIVE_TYPE";
+ case gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT:
+ return "gcvSTATUS_MISSING_OUTPUT_VERTEX_COUNT";
+ case gcvSTATUS_NON_INVOCATION_ID_AS_INDEX:
+ return "gcvSTATUS_NON_INVOCATION_ID_AS_INDEX";
+ case gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH:
+ return "gcvSTATUS_INPUT_ARRAY_SIZE_MISMATCH";
+ case gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH:
+ return "gcvSTATUS_OUTPUT_ARRAY_SIZE_MISMATCH";
+
+ /* Compiler errors. */
+ case gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR:
+ return "gcvSTATUS_COMPILER_FE_PREPROCESSOR_ERROR";
+ case gcvSTATUS_COMPILER_FE_PARSER_ERROR:
+ return "gcvSTATUS_COMPILER_FE_PARSER_ERROR";
+ default:
+ return "nil";
+ }
+}
+
+/*******************************************************************************
+***** Kernel Dump **************************************************************
+*******************************************************************************/
+
+/*
+ * TODO: Dump to file is only valid in linux currently.
+ */
+#ifndef gcmkDUMP_STRING
+# define gcmkDUMP_STRING(os, s) gcmkOUTPUT_STRING((s))
+#endif
+
+static gcmkDECLARE_MUTEX(_dumpMutex);
+static gctCHAR _dumpStorage[512];
+
+/*******************************************************************************
+**
+** gckOS_Dump
+**
+** Formated print string to dump pool.
+**
+** INPUT:
+**
+** gctCONST_STRING Format
+** String format.
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_Dump(
+ IN gckOS Os,
+ IN gctCONST_STRING Format,
+ ...
+ )
+{
+ char buffer[256];
+ gctINT len;
+ gctARGUMENTS args;
+
+ gcmkARGUMENTS_START(args, Format);
+ len = gcmkVSPRINTF(buffer, gcmSIZEOF(buffer) - 2, Format, &args);
+ gcmkARGUMENTS_END(args);
+
+ if (len > 0)
+ {
+ if (buffer[len - 1] != '\n')
+ {
+ buffer[len] = '\n';
+ buffer[len + 1] = '\0';
+ }
+
+ gcmkMUTEX_LOCK(_dumpMutex);
+ gcmkDUMP_STRING(Os, buffer);
+ gcmkMUTEX_UNLOCK(_dumpMutex);
+ }
+}
+
+static void
+_DumpUserString(
+ IN gckOS Os,
+ IN gctPOINTER UserStr,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctSIZE_T offset = 0;
+ gctSIZE_T length = 0;
+ gctBOOL needCopy = gcvTRUE;
+ const gctSIZE_T maxLength = gcmSIZEOF(_dumpStorage) - 1;
+
+ gcmkVERIFY_OK(gckOS_QueryNeedCopy(Os, 0, &needCopy));
+
+ gcmkMUTEX_LOCK(_dumpMutex);
+
+ while (offset < Size)
+ {
+ length = maxLength < (Size - offset) ? maxLength : (Size - offset);
+
+ /* Copy or map from user. */
+ if (needCopy)
+ {
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Os,
+ _dumpStorage,
+ UserStr,
+ length
+ ));
+ }
+ else
+ {
+ gctPOINTER ptr = gcvNULL;
+
+ gcmkONERROR(gckOS_MapUserPointer(
+ Os,
+ UserStr,
+ length,
+ (gctPOINTER *)&ptr
+ ));
+
+ gckOS_MemCopy(_dumpStorage, ptr, length);
+ gckOS_UnmapUserPointer(Os, UserStr, length, ptr);
+ }
+
+ _dumpStorage[length] = '\0';
+ gcmkDUMP_STRING(Os, _dumpStorage);
+
+ UserStr = (gctUINT8_PTR)UserStr + length;
+ offset += length;
+ }
+
+ gcmkDUMP_STRING(Os, "\n");
+
+OnError:
+ gcmkMUTEX_UNLOCK(_dumpMutex);
+}
+
+static void
+_DumpDataBuffer(
+ IN gckOS Os,
+ IN gceDUMP_BUFFER_TYPE Type,
+ IN gctPOINTER Data,
+ IN gctUINT64 Address,
+ IN gctSIZE_T Size
+ )
+{
+ gceSTATUS status = gcvSTATUS_OK;
+ gctSIZE_T offset = 0;
+ gctSIZE_T length = 0;
+ gctBOOL needCopy = gcvTRUE;
+ gctCONST_STRING dumpTag;
+ char buffer[256];
+ const gctSIZE_T maxLength = gcmSIZEOF(_dumpStorage);
+
+ switch (Type)
+ {
+ case gcvDUMP_BUFFER_VERIFY:
+ dumpTag = "verify";
+ break;
+ case gcvDUMP_BUFFER_PHYSICAL_MEMORY:
+ dumpTag = "physical";
+ break;
+ default:
+ dumpTag = "memory";
+ break;
+ }
+
+ if (Type <= gcvDUMP_BUFFER_USER_TYPE_LAST)
+ {
+ gcmkVERIFY_OK(gckOS_QueryNeedCopy(Os, 0, &needCopy));
+ }
+
+ gcmkMUTEX_LOCK(_dumpMutex);
+
+ /* Form and print the opening string. */
+ if (Type == gcvDUMP_BUFFER_PHYSICAL_MEMORY)
+ {
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ "@[%s 0x%010llX 0x%08X\n",
+ dumpTag, (unsigned long long)Address, (gctUINT32)Size);
+ }
+ else
+ {
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ "@[%s 0x%08X 0x%08X\n",
+ dumpTag, (gctUINT32)Address, (gctUINT32)Size);
+ }
+
+ gcmkDUMP_STRING(Os, buffer);
+
+
+ while (offset < Size)
+ {
+ gctPOINTER data = gcvNULL;
+ gctUINT32_PTR ptr;
+ gctUINT8_PTR bytePtr;
+ gctSIZE_T count, tailByteCount;
+
+ length = maxLength < (Size - offset) ? maxLength : (Size - offset);
+ count = length / 4;
+ tailByteCount = length % 4;
+
+ ptr = (gctUINT32_PTR)Data;
+
+ if (Type <= gcvDUMP_BUFFER_USER_TYPE_LAST)
+ {
+ /* Copy or map from user. */
+ if (needCopy)
+ {
+ gcmkONERROR(gckOS_CopyFromUserData(
+ Os,
+ _dumpStorage,
+ Data,
+ length
+ ));
+
+ ptr = (gctUINT32_PTR)_dumpStorage;
+ }
+ else
+ {
+ gcmkONERROR(gckOS_MapUserPointer(
+ Os,
+ Data,
+ length,
+ (gctPOINTER *)&data
+ ));
+
+ ptr = (gctUINT32_PTR)data;
+ }
+ }
+
+ while (count >= 4)
+ {
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ " 0x%08X 0x%08X 0x%08X 0x%08X\n",
+ ptr[0], ptr[1], ptr[2], ptr[3]);
+
+ ptr += 4;
+ count -= 4;
+
+ gcmkDUMP_STRING(Os, buffer);
+ }
+
+ switch (count)
+ {
+ case 3:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ " 0x%08X 0x%08X 0x%08X",
+ ptr[0], ptr[1], ptr[2]);
+ break;
+ case 2:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ " 0x%08X 0x%08X",
+ ptr[0], ptr[1]);
+ break;
+ case 1:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, " 0x%08X", ptr[0]);
+ break;
+ }
+
+ if (count > 0)
+ {
+ gcmkDUMP_STRING(Os, buffer);
+ }
+
+ bytePtr = (gctUINT8_PTR)(ptr + count);
+
+ if (!count && tailByteCount)
+ {
+ /* There is an extra space for the new line. */
+ gcmkDUMP_STRING(Os, " ");
+ }
+
+ switch (tailByteCount)
+ {
+ case 3:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ " 0x00%02X%02X%02X",
+ bytePtr[2], bytePtr[1], bytePtr[0]);
+ break;
+ case 2:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ " 0x0000%02X%02X",
+ bytePtr[1], bytePtr[0]);
+ break;
+ case 1:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1,
+ " 0x000000%02X", bytePtr[0]);
+ break;
+ }
+
+ if (tailByteCount)
+ {
+ gcmkDUMP_STRING(Os, buffer);
+ }
+
+ if (count || tailByteCount)
+ {
+ gcmkDUMP_STRING(Os, "\n");
+ }
+
+ if (Type <= gcvDUMP_BUFFER_USER_TYPE_LAST && !needCopy)
+ {
+ gckOS_UnmapUserPointer(Os, Data, length, data);
+ }
+ /* advance to next batch. */
+ Data = (gctUINT8_PTR)Data + length;
+ offset += length;
+ }
+
+OnError:
+ gcmkSPRINTF(buffer, gcmSIZEOF(buffer) - 1, "] -- %s\n", dumpTag);
+ gcmkDUMP_STRING(Os, buffer);
+
+ gcmkMUTEX_UNLOCK(_dumpMutex);
+}
+
+/*******************************************************************************
+**
+** gckOS_DumpBuffer
+**
+** Print the contents of the specified buffer.
+**
+** INPUT:
+**
+** gckOS Os
+** Pointer to gckOS object.
+**
+** gceDUMP_BUFFER_TYPE Type
+** Buffer type.
+**
+** gctPOINTER Buffer
+** Pointer to the buffer to print.
+**
+** gctUINT64 Address
+** Address.
+**
+** gctUINT Size
+** Size of the buffer.
+**
+**
+** OUTPUT:
+**
+** Nothing.
+*/
+void
+gckOS_DumpBuffer(
+ IN gckOS Os,
+ IN gceDUMP_BUFFER_TYPE Type,
+ IN gctPOINTER Buffer,
+ IN gctUINT64 Address,
+ IN gctSIZE_T Size
+ )
+{
+ if (!Buffer)
+ {
+ return;
+ }
+
+ /* memory dump below. */
+ if (Type >= gcvDUMP_BUFFER_TYPE_COUNT)
+ {
+ gcmkPRINT("#[ERROR: invalid buffer type]\n");
+ return;
+ }
+
+ if (Type == gcvDUMP_BUFFER_USER_STRING)
+ {
+ _DumpUserString(Os, Buffer, Size);
+ }
+ else
+ {
+ _DumpDataBuffer(Os, Type, Buffer, Address, Size);
+ }
+}