/*--------------------------------------------------------------------*//*! * \brief Start image set * \param log qpTestLog instance * \param name Unique identifier for the set * \param description Human readable description * \return true if ok, false otherwise *//*--------------------------------------------------------------------*/ deBool qpTestLog_startImageSet (qpTestLog* log, const char* name, const char* description) { qpXmlAttribute attribs[4]; int numAttribs = 0; DE_ASSERT(log && name); deMutex_lock(log->lock); attribs[numAttribs++] = qpSetStringAttrib("Name", name); if (description) attribs[numAttribs++] = qpSetStringAttrib("Description", description); /* <ImageSet Name="<name>"> */ if (!qpXmlWriter_startElement(log->writer, "ImageSet", numAttribs, attribs)) { qpPrintf("qpTestLog_startImageSet(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_IMAGESET)); deMutex_unlock(log->lock); return DE_TRUE; }
deBool qpTestLog_writeValueInfo (qpTestLog* log, const char* name, const char* description, const char* unit, qpSampleValueTag tag) { const char* tagName = QP_LOOKUP_STRING(s_qpSampleValueTagMap, tag); int numAttribs = 0; qpXmlAttribute attribs[4]; DE_ASSERT(log && name && description && tagName); deMutex_lock(log->lock); DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SAMPLEINFO); attribs[numAttribs++] = qpSetStringAttrib("Name", name); attribs[numAttribs++] = qpSetStringAttrib("Description", description); attribs[numAttribs++] = qpSetStringAttrib("Tag", tagName); if (unit) attribs[numAttribs++] = qpSetStringAttrib("Unit", unit); if (!qpXmlWriter_startElement(log->writer, "ValueInfo", numAttribs, attribs) || !qpXmlWriter_endElement(log->writer, "ValueInfo")) { qpPrintf("qpTestLog_writeValueInfo(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } deMutex_unlock(log->lock); return DE_TRUE; }
static deBool qpTestLog_writeKeyValuePair (qpTestLog* log, const char* elementName, const char* name, const char* description, const char* unit, qpKeyValueTag tag, const char* text) { const char* tagString = QP_LOOKUP_STRING(s_qpTagMap, tag); qpXmlAttribute attribs[8]; int numAttribs = 0; DE_ASSERT(log && elementName && text); deMutex_lock(log->lock); /* Fill in attributes. */ if (name) attribs[numAttribs++] = qpSetStringAttrib("Name", name); if (description) attribs[numAttribs++] = qpSetStringAttrib("Description", description); if (tagString) attribs[numAttribs++] = qpSetStringAttrib("Tag", tagString); if (unit) attribs[numAttribs++] = qpSetStringAttrib("Unit", unit); if (!qpXmlWriter_startElement(log->writer, elementName, numAttribs, attribs) || !qpXmlWriter_writeString(log->writer, text) || !qpXmlWriter_endElement(log->writer, elementName)) { qpPrintf("qpTestLog_writeKeyValuePair(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Log start of test case * \param log qpTestLog instance * \param testCasePath Full test case path (as seen in Candy). * \param testCaseType Test case type * \return true if ok, false otherwise *//*--------------------------------------------------------------------*/ deBool qpTestLog_startCase (qpTestLog* log, const char* testCasePath, qpTestCaseType testCaseType) { const char* typeStr = QP_LOOKUP_STRING(s_qpTestTypeMap, testCaseType); int numResultAttribs = 0; qpXmlAttribute resultAttribs[8]; DE_ASSERT(log && testCasePath && (testCasePath[0] != 0)); deMutex_lock(log->lock); DE_ASSERT(!log->isCaseOpen); DE_ASSERT(ContainerStack_isEmpty(&log->containerStack)); /* Flush XML and write out #beginTestCaseResult. */ qpXmlWriter_flush(log->writer); fprintf(log->outputFile, "\n#beginTestCaseResult %s\n", testCasePath); qpTestLog_flushFile(log); log->isCaseOpen = DE_TRUE; /* Fill in attributes. */ resultAttribs[numResultAttribs++] = qpSetStringAttrib("Version", LOG_FORMAT_VERSION); resultAttribs[numResultAttribs++] = qpSetStringAttrib("CasePath", testCasePath); resultAttribs[numResultAttribs++] = qpSetStringAttrib("CaseType", typeStr); if (!qpXmlWriter_startDocument(log->writer) || !qpXmlWriter_startElement(log->writer, "TestCaseResult", numResultAttribs, resultAttribs)) { qpPrintf("qpTestLog_startCase(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Write a OpenGL ES shader into the log. * \param type Shader type * \param source Shader source * \param compileOk Shader compilation result, false on failure * \param infoLog Implementation provided shader compilation log *//*--------------------------------------------------------------------*/ deBool qpTestLog_writeShader (qpTestLog* log, qpShaderType type, const char* source, deBool compileOk, const char* infoLog) { const char* tagName = QP_LOOKUP_STRING(s_qpShaderTypeMap, type); const char* sourceStr = ((log->flags & QP_TEST_LOG_EXCLUDE_SHADER_SOURCES) == 0 || !compileOk) ? source : ""; int numShaderAttribs = 0; qpXmlAttribute shaderAttribs[4]; deMutex_lock(log->lock); DE_ASSERT(source); DE_ASSERT(ContainerStack_getTop(&log->containerStack) == CONTAINERTYPE_SHADERPROGRAM); shaderAttribs[numShaderAttribs++] = qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail"); if (!qpXmlWriter_startElement(log->writer, tagName, numShaderAttribs, shaderAttribs) || !qpXmlWriter_writeStringElement(log->writer, "ShaderSource", sourceStr) || !qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog) || !qpXmlWriter_endElement(log->writer, tagName)) { qpPrintf("qpTestLog_writeShader(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Log end of test case * \param log qpTestLog instance * \param result Test result * \param description Description of a problem in case of error * \return true if ok, false otherwise *//*--------------------------------------------------------------------*/ deBool qpTestLog_endCase (qpTestLog* log, qpTestResult result, const char* resultDetails) { const char* statusStr = QP_LOOKUP_STRING(s_qpTestResultMap, result); qpXmlAttribute statusAttrib = qpSetStringAttrib("StatusCode", statusStr); deMutex_lock(log->lock); DE_ASSERT(log->isCaseOpen); DE_ASSERT(ContainerStack_isEmpty(&log->containerStack)); /* <Result StatusCode="Pass">Result details</Result> * </TestCaseResult> */ if (!qpXmlWriter_startElement(log->writer, "Result", 1, &statusAttrib) || (resultDetails && !qpXmlWriter_writeString(log->writer, resultDetails)) || !qpXmlWriter_endElement(log->writer, "Result") || !qpXmlWriter_endElement(log->writer, "TestCaseResult") || !qpXmlWriter_endDocument(log->writer)) /* Close any XML elements still open */ { qpPrintf("qpTestLog_endCase(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } /* Flush XML and write #endTestCaseResult. */ qpXmlWriter_flush(log->writer); fprintf(log->outputFile, "\n#endTestCaseResult\n"); if (!(log->flags & QP_TEST_LOG_NO_FLUSH)) qpTestLog_flushFile(log); log->isCaseOpen = DE_FALSE; deMutex_unlock(log->lock); return DE_TRUE; }
deBool qpTestLog_startSampleList (qpTestLog* log, const char* name, const char* description) { int numAttribs = 0; qpXmlAttribute attribs[2]; DE_ASSERT(log && name && description); deMutex_lock(log->lock); attribs[numAttribs++] = qpSetStringAttrib("Name", name); attribs[numAttribs++] = qpSetStringAttrib("Description", description); if (!qpXmlWriter_startElement(log->writer, "SampleList", numAttribs, attribs)) { qpPrintf("qpTestLog_startSampleList(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SAMPLELIST)); deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Write OpenCL kernel compilation results into the log *//*--------------------------------------------------------------------*/ deBool qpTestLog_writeCompileInfo (qpTestLog* log, const char* name, const char* description, deBool compileOk, const char* infoLog) { int numAttribs = 0; qpXmlAttribute attribs[3]; DE_ASSERT(log && name && description && infoLog); deMutex_lock(log->lock); attribs[numAttribs++] = qpSetStringAttrib("Name", name); attribs[numAttribs++] = qpSetStringAttrib("Description", description); attribs[numAttribs++] = qpSetStringAttrib("CompileStatus", compileOk ? "OK" : "Fail"); if (!qpXmlWriter_startElement(log->writer, "CompileInfo", numAttribs, attribs) || !qpXmlWriter_writeStringElement(log->writer, "InfoLog", infoLog) || !qpXmlWriter_endElement(log->writer, "CompileInfo")) { qpPrintf("qpTestLog_writeCompileInfo(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Write an EGL config inside an EGL config set * \see qpElgConfigInfo for details *//*--------------------------------------------------------------------*/ deBool qpTestLog_writeEglConfig (qpTestLog* log, const qpEglConfigInfo* config) { qpXmlAttribute attribs[64]; int numAttribs = 0; DE_ASSERT(log && config); deMutex_lock(log->lock); attribs[numAttribs++] = qpSetIntAttrib ("BufferSize", config->bufferSize); attribs[numAttribs++] = qpSetIntAttrib ("RedSize", config->redSize); attribs[numAttribs++] = qpSetIntAttrib ("GreenSize", config->greenSize); attribs[numAttribs++] = qpSetIntAttrib ("BlueSize", config->blueSize); attribs[numAttribs++] = qpSetIntAttrib ("LuminanceSize", config->luminanceSize); attribs[numAttribs++] = qpSetIntAttrib ("AlphaSize", config->alphaSize); attribs[numAttribs++] = qpSetIntAttrib ("AlphaMaskSize", config->alphaMaskSize); attribs[numAttribs++] = qpSetBoolAttrib ("BindToTextureRGB", config->bindToTextureRGB); attribs[numAttribs++] = qpSetBoolAttrib ("BindToTextureRGBA", config->bindToTextureRGBA); attribs[numAttribs++] = qpSetStringAttrib ("ColorBufferType", config->colorBufferType); attribs[numAttribs++] = qpSetStringAttrib ("ConfigCaveat", config->configCaveat); attribs[numAttribs++] = qpSetIntAttrib ("ConfigID", config->configID); attribs[numAttribs++] = qpSetStringAttrib ("Conformant", config->conformant); attribs[numAttribs++] = qpSetIntAttrib ("DepthSize", config->depthSize); attribs[numAttribs++] = qpSetIntAttrib ("Level", config->level); attribs[numAttribs++] = qpSetIntAttrib ("MaxPBufferWidth", config->maxPBufferWidth); attribs[numAttribs++] = qpSetIntAttrib ("MaxPBufferHeight", config->maxPBufferHeight); attribs[numAttribs++] = qpSetIntAttrib ("MaxPBufferPixels", config->maxPBufferPixels); attribs[numAttribs++] = qpSetIntAttrib ("MaxSwapInterval", config->maxSwapInterval); attribs[numAttribs++] = qpSetIntAttrib ("MinSwapInterval", config->minSwapInterval); attribs[numAttribs++] = qpSetBoolAttrib ("NativeRenderable", config->nativeRenderable); attribs[numAttribs++] = qpSetStringAttrib ("RenderableType", config->renderableType); attribs[numAttribs++] = qpSetIntAttrib ("SampleBuffers", config->sampleBuffers); attribs[numAttribs++] = qpSetIntAttrib ("Samples", config->samples); attribs[numAttribs++] = qpSetIntAttrib ("StencilSize", config->stencilSize); attribs[numAttribs++] = qpSetStringAttrib ("SurfaceTypes", config->surfaceTypes); attribs[numAttribs++] = qpSetStringAttrib ("TransparentType", config->transparentType); attribs[numAttribs++] = qpSetIntAttrib ("TransparentRedValue", config->transparentRedValue); attribs[numAttribs++] = qpSetIntAttrib ("TransparentGreenValue", config->transparentGreenValue); attribs[numAttribs++] = qpSetIntAttrib ("TransparentBlueValue", config->transparentBlueValue); DE_ASSERT(numAttribs <= DE_LENGTH_OF_ARRAY(attribs)); if (!qpXmlWriter_startElement(log->writer, "EglConfig", numAttribs, attribs) || !qpXmlWriter_endElement(log->writer, "EglConfig")) { qpPrintf("qpTestLog_writeEglConfig(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Write a OpenGL ES shader program into the log. * \param linkOk Shader program link result, false on failure * \param linkInfoLog Implementation provided linkage log *//*--------------------------------------------------------------------*/ deBool qpTestLog_startShaderProgram (qpTestLog* log, deBool linkOk, const char* linkInfoLog) { qpXmlAttribute programAttribs[4]; int numProgramAttribs = 0; DE_ASSERT(log); deMutex_lock(log->lock); programAttribs[numProgramAttribs++] = qpSetStringAttrib("LinkStatus", linkOk ? "OK" : "Fail"); if (!qpXmlWriter_startElement(log->writer, "ShaderProgram", numProgramAttribs, programAttribs) || !qpXmlWriter_writeStringElement(log->writer, "InfoLog", linkInfoLog)) { qpPrintf("qpTestLog_startShaderProgram(): Writing XML failed\n"); deMutex_unlock(log->lock); return DE_FALSE; } DE_ASSERT(ContainerStack_push(&log->containerStack, CONTAINERTYPE_SHADERPROGRAM)); deMutex_unlock(log->lock); return DE_TRUE; }
/*--------------------------------------------------------------------*//*! * \brief Write base64 encoded raw image data into log * \param log qpTestLog instance * \param name Unique name (matching names can be compared across BatchResults). * \param description Textual description (shown in Candy). * \param compressionMode Compression mode * \param imageFormat Color format * \param width Width in pixels * \param height Height in pixels * \param stride Data stride (offset between rows) * \param data Pointer to pixel data * \return 0 if OK, otherwise <0 *//*--------------------------------------------------------------------*/ deBool qpTestLog_writeImage ( qpTestLog* log, const char* name, const char* description, qpImageCompressionMode compressionMode, qpImageFormat imageFormat, int width, int height, int stride, const void* data) { char widthStr[32]; char heightStr[32]; qpXmlAttribute attribs[8]; int numAttribs = 0; Buffer compressedBuffer; const void* writeDataPtr = DE_NULL; size_t writeDataBytes = ~(size_t)0; DE_ASSERT(log && name); DE_ASSERT(deInRange32(width, 1, 32768)); DE_ASSERT(deInRange32(height, 1, 32768)); DE_ASSERT(data); if (log->flags & QP_TEST_LOG_EXCLUDE_IMAGES) return DE_TRUE; /* Image not logged. */ Buffer_init(&compressedBuffer); /* BEST compression mode defaults to PNG. */ if (compressionMode == QP_IMAGE_COMPRESSION_MODE_BEST) { #if defined(QP_SUPPORT_PNG) compressionMode = QP_IMAGE_COMPRESSION_MODE_PNG; #else compressionMode = QP_IMAGE_COMPRESSION_MODE_NONE; #endif } #if defined(QP_SUPPORT_PNG) /* Try storing with PNG compression. */ if (compressionMode == QP_IMAGE_COMPRESSION_MODE_PNG) { deBool compressOk = compressImagePNG(&compressedBuffer, imageFormat, width, height, stride, data); if (compressOk) { writeDataPtr = compressedBuffer.data; writeDataBytes = compressedBuffer.size; } else { /* Fall-back to default compression. */ qpPrintf("WARNING: PNG compression failed -- storing image uncompressed.\n"); compressionMode = QP_IMAGE_COMPRESSION_MODE_NONE; } } #endif /* Handle image compression. */ switch (compressionMode) { case QP_IMAGE_COMPRESSION_MODE_NONE: { int pixelSize = imageFormat == QP_IMAGE_FORMAT_RGB888 ? 3 : 4; int packedStride = pixelSize*width; if (packedStride == stride) writeDataPtr = data; else { /* Need to re-pack pixels. */ if (Buffer_resize(&compressedBuffer, (size_t)(packedStride*height))) { int row; for (row = 0; row < height; row++) memcpy(&compressedBuffer.data[packedStride*row], &((const deUint8*)data)[row*stride], (size_t)(pixelSize*width)); } else { qpPrintf("ERROR: Failed to pack pixels for writing.\n"); Buffer_deinit(&compressedBuffer); return DE_FALSE; } } writeDataBytes = (size_t)(packedStride*height); break; } #if defined(QP_SUPPORT_PNG) case QP_IMAGE_COMPRESSION_MODE_PNG: DE_ASSERT(writeDataPtr); /* Already handled. */ break; #endif default: qpPrintf("qpTestLog_writeImage(): Unknown compression mode: %s\n", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode)); Buffer_deinit(&compressedBuffer); return DE_FALSE; } /* Fill in attributes. */ int32ToString(width, widthStr); int32ToString(height, heightStr); attribs[numAttribs++] = qpSetStringAttrib("Name", name); attribs[numAttribs++] = qpSetStringAttrib("Width", widthStr); attribs[numAttribs++] = qpSetStringAttrib("Height", heightStr); attribs[numAttribs++] = qpSetStringAttrib("Format", QP_LOOKUP_STRING(s_qpImageFormatMap, imageFormat)); attribs[numAttribs++] = qpSetStringAttrib("CompressionMode", QP_LOOKUP_STRING(s_qpImageCompressionModeMap, compressionMode)); if (description) attribs[numAttribs++] = qpSetStringAttrib("Description", description); /* \note Log lock is acquired after compression! */ deMutex_lock(log->lock); /* <Image ID="result" Name="Foobar" Width="640" Height="480" Format="RGB888" CompressionMode="None">base64 data</Image> */ if (!qpXmlWriter_startElement(log->writer, "Image", numAttribs, attribs) || !qpXmlWriter_writeBase64(log->writer, (const deUint8*)writeDataPtr, writeDataBytes) || !qpXmlWriter_endElement(log->writer, "Image")) { qpPrintf("qpTestLog_writeImage(): Writing XML failed\n"); deMutex_unlock(log->lock); Buffer_deinit(&compressedBuffer); return DE_FALSE; } deMutex_unlock(log->lock); /* Free compressed data if allocated. */ Buffer_deinit(&compressedBuffer); return DE_TRUE; }