From patchwork Wed Jan 16 22:00:28 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tom Gall X-Patchwork-Id: 14088 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id F2F1D23F02 for ; Wed, 16 Jan 2013 22:00:38 +0000 (UTC) Received: from mail-vc0-f174.google.com (mail-vc0-f174.google.com [209.85.220.174]) by fiordland.canonical.com (Postfix) with ESMTP id 57816A19714 for ; Wed, 16 Jan 2013 22:00:38 +0000 (UTC) Received: by mail-vc0-f174.google.com with SMTP id d16so1840579vcd.5 for ; Wed, 16 Jan 2013 14:00:37 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=yj5dKk9fsxWDfP8tzU5lrfWMR7RC2qnfdgNxUyJzt1I=; b=ZP1oH5BsqLNSpRQVgN546r1Nh5Yi81PfOjFkTVB21FO4iKaJyEtjqFM2Fp5vrC2PM1 iFF9lusvPvCy9lps2uCtLTwhF1O49Dw+NEB+5H3en6zCpIhf09ysmT04WPkM8cbeDdbO yKxRIsb1RA+FrQzeaH5nB8/hO57ynTOsOHrpvGqMmkMIERh5xS9T/dnmmHt32SFaKEmP MuBf6P8pmsALBTDONiHgBCPABff7JEqB/7gsFobXMqAduF6h75P5DmNZ5dTtSG7C1uMb 1vnjdPngiv+kPVJNhHtlcFutVTJgkerWDM4MEyLc3sQTGR6zXw+bC3secNaCxPBJo7mw lH/A== X-Received: by 10.52.70.205 with SMTP id o13mr2646030vdu.75.1358373637620; Wed, 16 Jan 2013 14:00:37 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.145.101 with SMTP id st5csp189956veb; Wed, 16 Jan 2013 14:00:36 -0800 (PST) X-Received: by 10.42.212.4 with SMTP id gq4mr1700893icb.38.1358373635526; Wed, 16 Jan 2013 14:00:35 -0800 (PST) Received: from mail-ie0-f182.google.com (mail-ie0-f182.google.com [209.85.223.182]) by mx.google.com with ESMTPS id w10si21414337icv.58.2013.01.16.14.00.34 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 16 Jan 2013 14:00:35 -0800 (PST) Received-SPF: neutral (google.com: 209.85.223.182 is neither permitted nor denied by best guess record for domain of tom.gall@linaro.org) client-ip=209.85.223.182; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.223.182 is neither permitted nor denied by best guess record for domain of tom.gall@linaro.org) smtp.mail=tom.gall@linaro.org Received: by mail-ie0-f182.google.com with SMTP id s9so3578084iec.13 for ; Wed, 16 Jan 2013 14:00:34 -0800 (PST) X-Received: by 10.42.212.8 with SMTP id gq8mr1678254icb.48.1358373634284; Wed, 16 Jan 2013 14:00:34 -0800 (PST) Received: from localhost.localdomain ([70.35.96.184]) by mx.google.com with ESMTPS id pr7sm5329345igc.16.2013.01.16.14.00.33 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 16 Jan 2013 14:00:33 -0800 (PST) From: Tom Gall To: patches@linaro.org Cc: Tom Gall Subject: =?UTF-8?q?=5BPATCH=201/1=5D=20gles2=3A=20add=20api/glReadPixels?= Date: Wed, 16 Jan 2013 16:00:28 -0600 Message-Id: <1358373628-25015-1-git-send-email-tom.gall@linaro.org> X-Mailer: git-send-email 1.7.10.4 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQnVF3m4HxFgBSHpuibbnC8lkOVxWQsbpZLaB5smjI3I+nqSDjfXum3UUL2Rf4QKBIIZGdWK v2 - restructured approach to be data driven, as well as separating valid and invalid variations into separate tests. Tests glReadPixels specifically for OpenGL ES2 2.0. Covers a variety of formats and types, both valid and invalid. Signed-off-by: Tom Gall --- tests/spec/gles-2.0/CMakeLists.txt | 2 + tests/spec/gles-2.0/api/CMakeLists.gles2.txt | 8 + tests/spec/gles-2.0/api/CMakeLists.txt | 1 + tests/spec/gles-2.0/api/glreadpixels-common.c | 342 ++++++++++++++++++++++++ tests/spec/gles-2.0/api/glreadpixels-common.h | 77 ++++++ tests/spec/gles-2.0/api/glreadpixels-invalid.c | 284 ++++++++++++++++++++ tests/spec/gles-2.0/api/glreadpixels.c | 293 ++++++++++++++++++++ 7 files changed, 1007 insertions(+) create mode 100644 tests/spec/gles-2.0/api/CMakeLists.gles2.txt create mode 100644 tests/spec/gles-2.0/api/CMakeLists.txt create mode 100644 tests/spec/gles-2.0/api/glreadpixels-common.c create mode 100644 tests/spec/gles-2.0/api/glreadpixels-common.h create mode 100644 tests/spec/gles-2.0/api/glreadpixels-invalid.c create mode 100644 tests/spec/gles-2.0/api/glreadpixels.c diff --git a/tests/spec/gles-2.0/CMakeLists.txt b/tests/spec/gles-2.0/CMakeLists.txt index 144a306..fb759f6 100644 --- a/tests/spec/gles-2.0/CMakeLists.txt +++ b/tests/spec/gles-2.0/CMakeLists.txt @@ -1 +1,3 @@ +add_subdirectory (api) + piglit_include_target_api() diff --git a/tests/spec/gles-2.0/api/CMakeLists.gles2.txt b/tests/spec/gles-2.0/api/CMakeLists.gles2.txt new file mode 100644 index 0000000..c489430 --- /dev/null +++ b/tests/spec/gles-2.0/api/CMakeLists.gles2.txt @@ -0,0 +1,8 @@ +link_libraries( + piglitutil_${piglit_target_api} + ) + +piglit_add_executable(glreadpixels_gles2 glreadpixels.c glreadpixels-common.c) +piglit_add_executable(glreadpixels-invalid_gles2 glreadpixels-invalid.c glreadpixels-common.c) + +# vim: ft=cmake: diff --git a/tests/spec/gles-2.0/api/CMakeLists.txt b/tests/spec/gles-2.0/api/CMakeLists.txt new file mode 100644 index 0000000..144a306 --- /dev/null +++ b/tests/spec/gles-2.0/api/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/gles-2.0/api/glreadpixels-common.c b/tests/spec/gles-2.0/api/glreadpixels-common.c new file mode 100644 index 0000000..34ffcf8 --- /dev/null +++ b/tests/spec/gles-2.0/api/glreadpixels-common.c @@ -0,0 +1,342 @@ +/* + * Copyright © 2013 Linaro Inc + * + * 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 (including the next + * paragraph) 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. + */ + +/** + * Common code for testing glReadPixels + * as specified by the OpenGL ES 2.0.25 spec. + * + * \author Tom Gall + */ + +#include +#include +#include "piglit-util-gl-common.h" +#include "glreadpixels-common.h" + +void +clear_buffer(GLubyte *buffer) +{ + memset(buffer, TEST_PATTERN_BYTE, piglit_width*(piglit_height+50)*4); +} + + +enum piglit_result +check_buffer_RGB(GLubyte *buffer) +{ + pixel_f888 *p888; + int i,j; + + /* check that the rectangle was rendered correctly */ + for (i = piglit_height/4; i < piglit_height/4*3; i++) { + for (j = piglit_width/4; j < piglit_width/4*3; j++) { + p888 = (pixel_f888 *)(buffer + (((i * piglit_width)+ j) * 3)); + if (p888->red != 0xff && p888->green != 0x00 && + p888->blue != 0x00) + return PIGLIT_FAIL; + } + } + + /* check that the remaining area is black */ + for(i = 0; i < piglit_height/4; i++) { + for(j = 0; j < piglit_width; j++) { + p888 = (pixel_f888 *)(buffer + (((i*piglit_width)+ j) * 3)); + if (p888->red != 0x00 && p888->green != 0x00 && + p888->blue != 0x00) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4*3; i < piglit_height; i++) { + for(j = 0; j < piglit_width; j++) { + p888 = (pixel_f888 *)(buffer + (((i * piglit_width) + j) * 3)); + if (p888->red != 0x00 && p888->green != 0x00 && + p888->blue != 0x00) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = 0; j < piglit_width/4; j++) { + p888=(pixel_f888 *)(buffer + (((i * piglit_width) + j) * 3)); + if (p888->red != 0x00 && p888->green != 0x00 && + p888->blue != 0x00) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = piglit_width/4*3; j < piglit_width; j++) { + p888 = (pixel_f888 *)(buffer + (((i * piglit_width) + j) * 3)); + if (p888->red != 0x00 && p888->green != 0x00 && + p888->blue != 0x00) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} + + +enum piglit_result +check_buffer_RGBA(GLubyte *buffer) +{ + int i,j; + + /* check that the rectangle was rendered correctly */ + for (i = piglit_height/4; i < piglit_height/4*3; i++) { + for (j = piglit_width/4; j < piglit_width/4*3; j++) { + if (*(buffer + (i * j)) != 0xff && + *(buffer + ((i * j) + 1)) != 0x00 && + *(buffer + ((i * j) + 2)) != 0x00 && + *(buffer + ((i * j) + 3)) != 0xff) + return PIGLIT_FAIL; + } + } + /* check that the remaining area is black */ + for(i = 0; i < piglit_height/4; i++) { + for(j = 0; j < piglit_width; j++) { + if (*(buffer + (i * j)) != 0x00 && + *(buffer + ((i * j) + 1)) != 0x00 && + *(buffer + ((i * j) + 2)) != 0x00 && + *(buffer + ((i * j) + 3)) != 0xff) + return PIGLIT_FAIL; + } + } + for(i = (piglit_height/4)*3; i < piglit_height; i++) { + for(j = 0; j < piglit_width; j++) { + if (*(buffer + (i * j)) != 0x00 && + *(buffer + ((i * j) + 1)) != 0x00 && + *(buffer + ((i * j) + 2)) != 0x00 && + *(buffer + ((i * j) + 3)) != 0xff) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = 0; j < piglit_width/4; j++) { + if (*(buffer + (i * j)) != 0x00 && + *(buffer + ((i * j) + 1)) != 0x00 && + *(buffer + ((i * j) + 2)) != 0x00 && + *(buffer + ((i * j) + 3)) != 0xff) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = 240; j < piglit_width; j++) { + if (*(buffer + (i * j)) != 0x00 && + *(buffer + ((i * j) + 1)) != 0x00 && + *(buffer + ((i * j) + 2)) != 0x00 && + *(buffer + ((i * j) + 3)) != 0xff) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} + + +enum piglit_result +check_buffer_ALPHA(GLubyte *buffer) +{ + int i,j; + + for(i = 0; i < piglit_height; i++) { + for(j = 0; j < piglit_width; j++) { + if (*(buffer + (i * piglit_height) + j) != 0xff) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} + + +enum piglit_result +check_buffer_is_not_changed(GLubyte *buffer) +{ + int i,j; + + for(i = 0; i < piglit_height; i++) { + for(j = 0; j < (piglit_width + 50); j++) { + if (*(buffer + (i * piglit_height) + j) != TEST_PATTERN_BYTE) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} + + +enum piglit_result +check_buffer_RGB_565(GLubyte *buffer) +{ + pixel_f565 *p565; + int i,j; + + /* check that the rectangle was rendered correctly */ + for (i = piglit_height/4; i < piglit_height/4*3; i++) { + for (j = piglit_width/4; j < piglit_width/4*3; j++) { + p565 = (pixel_f565 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p565->red != 0x1f && p565->blue != 0x00 && + p565->green != 0x00) + return PIGLIT_FAIL; + } + } + /* check that the remaining area is black */ + for(i = 0; i < piglit_height/4; i++) { + for(j = 0; j < piglit_width; j++) { + p565 = (pixel_f565 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p565->red != 0x00 && p565->blue != 0x00 && + p565->green != 0x00) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4*3; i < piglit_height; i++) { + for(j = 0; j < piglit_width; j++) { + p565 = (pixel_f565 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p565->red != 0x00 && p565->blue != 0x00 && + p565->green != 0x00) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = 0; j < piglit_width/4; j++) { + p565 = (pixel_f565 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p565->red != 0x00 && p565->green != 0x00 && + p565->blue != 0x00) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = piglit_width/4*3; j < piglit_width; j++) { + p565 = (pixel_f565 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p565->red != 0x00 && p565->green != 0x00 && + p565->blue != 0x00) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} + + +enum piglit_result +check_buffer_RGBA_5551(GLubyte *buffer) +{ + pixel_f5551 *p5551; + int i,j; + + /* check that the rectangle was rendered correctly */ + for (i = piglit_height/4; i < piglit_height/4*3; i++) { + for (j = piglit_width/4; j < piglit_width/4*3; j++) { + p5551 = (pixel_f5551 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p5551->red != 0x1f && p5551->blue != 0x00 && + p5551->green != 0x00 && p5551->alpha != 0x1) + return PIGLIT_FAIL; + } + } + /* check that the remaining area is black */ + for(i = 0; i < piglit_height/4; i++) { + for(j = 0; j < piglit_width; j++) { + p5551 = (pixel_f5551 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p5551->red!=0x00 && p5551->green!=0x00 && + p5551->blue!=0x00 && p5551->alpha!=0x1) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4*3; i < piglit_height; i++) { + for(j = 0; j < piglit_width; j++) { + p5551 = (pixel_f5551 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p5551->red != 0x00 && p5551->green != 0x00 && + p5551->blue != 0x00 && p5551->alpha != 0x1) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = 0; j < piglit_width/4; j++) { + p5551 = (pixel_f5551 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p5551->red != 0x00 && p5551->green != 0x00 && + p5551->blue != 0x00 && p5551->alpha != 0x1) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = piglit_width/4*3; j < piglit_width; j++) { + p5551 = (pixel_f5551 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p5551->red != 0x00 && p5551->green != 0x00 && + p5551->blue != 0x00 && p5551->alpha != 0x1) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} + + +enum piglit_result +check_buffer_RGBA_4444(GLubyte *buffer) +{ + pixel_f4444 *p4444; + int i,j; + + /* check that the rectangle was rendered correctly */ + for (i = piglit_height/4; i < piglit_height/4*3; i++) { + for (j = piglit_width/4; j < piglit_width/4*3; j++) { + p4444 = (pixel_f4444 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p4444->red != 0xf && p4444->green != 0x00 && + p4444->blue != 0x00 && p4444->alpha != 0xf) + return PIGLIT_FAIL; + } + } + /* check that the remaining area is black */ + for(i = 0; i < piglit_height/4; i++) { + for(j = 0; j < piglit_width; j++) { + p4444 = (pixel_f4444 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p4444->red != 0x00 && p4444->green != 0x00 && + p4444->blue != 0x00 && p4444->alpha != 0xf) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4*3; i < piglit_height; i++) { + for(j = 0; j < piglit_width; j++) { + p4444 = (pixel_f4444 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p4444->red != 0x00 && p4444->green != 0x00 && + p4444->blue != 0x00 && p4444->alpha != 0xf) + return PIGLIT_FAIL; + } + } + for(i = piglit_height/4; i < piglit_height/4*3; i++) { + for(j = 0; jred != 0x00 && p4444->green != 0x00 && + p4444->blue != 0x00 && p4444->alpha != 0xf) + return PIGLIT_FAIL; + } + } + for(i=piglit_height/4; i < piglit_height/4*3; i++) { + for(j = piglit_width/4*3; j < piglit_width; j++) { + p4444 = (pixel_f4444 *)(buffer + (((i * piglit_width) + j) * 2)); + if (p4444->red != 0x00 && p4444->green != 0x00 && + p4444->blue != 0x00 && p4444->alpha != 0xf) + return PIGLIT_FAIL; + } + } + + return PIGLIT_PASS; +} diff --git a/tests/spec/gles-2.0/api/glreadpixels-common.h b/tests/spec/gles-2.0/api/glreadpixels-common.h new file mode 100644 index 0000000..2bc1733 --- /dev/null +++ b/tests/spec/gles-2.0/api/glreadpixels-common.h @@ -0,0 +1,77 @@ +/* + * Copyright © 2013 Linaro Inc + * + * 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 (including the next + * paragraph) 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. + */ + +/** + * Common functions used by the glReadPixels test exercises. + * + * \author Tom Gall + */ + +#define WIDTH 320 +#define HEIGHT 200 +#define TEST_PATTERN_BYTE 0xA5 + +/* various pixel formats */ +typedef struct { + unsigned short red:5; + unsigned short green:6; + unsigned short blue:5; +} pixel_f565; +typedef struct { + unsigned short red:5; + unsigned short green:5; + unsigned short blue:5; + unsigned short alpha:1; +} pixel_f5551; +typedef struct { + unsigned short red:4; + unsigned short green:4; + unsigned short blue:4; + unsigned short alpha:4; +} pixel_f4444; +typedef struct { + unsigned char red; + unsigned char green; + unsigned char blue; +} pixel_f888; + +/* this is to create a mapping between the format and string + * representation. While both formats and types are GLenum type + * these are actually both typdefed to unsigned instead of being + * real enums. + */ +enum _format_key { _DEPTH_COMPONENT, _ALPHA, _RGB, _RGBA, + _LUMINANCE, _LUMINANCE_ALPHA, _x1800 }; + +enum _type_key { _UNSIGNED_BYTE, _UNSIGNED_SHORT_4444, + _UNSIGNED_SHORT_5551, _UNSIGNED_SHORT_565 }; + +enum piglit_result check_buffer_RGB(GLubyte *buffer); +enum piglit_result check_buffer_RGBA(GLubyte *buffer); +enum piglit_result check_buffer_ALPHA(GLubyte *buffer); +enum piglit_result check_buffer_is_not_changed(GLubyte *buffer); +enum piglit_result check_buffer_RGB_565(GLubyte *buffer); +enum piglit_result check_buffer_RGBA_5551(GLubyte *buffer); +enum piglit_result check_buffer_RGBA_4444(GLubyte *buffer); + +void clear_buffer(GLubyte *buffer); diff --git a/tests/spec/gles-2.0/api/glreadpixels-invalid.c b/tests/spec/gles-2.0/api/glreadpixels-invalid.c new file mode 100644 index 0000000..f113d2b --- /dev/null +++ b/tests/spec/gles-2.0/api/glreadpixels-invalid.c @@ -0,0 +1,284 @@ +/* + * Copyright © 2013 Linaro Inc + * + * 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 (including the next + * paragraph) 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. + */ + +/** + * This is test exercises glReadPixels + * as specified by the OpenGL ES 2.0.25 spec. + * + * \author Tom Gall + */ + +#include +#include +#include "piglit-util-gl-common.h" +#include "glreadpixels-common.h" + + +const char *format_strings [] = { + "GL_DEPTH_COMPONENT", + "GL_ALPHA", + "GL_RGB", + "GL_RGBA", + "GL_LUMINANCE", + "GL_LUMINANCE_ALPHA", + "0x1800" +}; + +const char *type_strings[] = { + "GL_UNSIGNED_BYTE", + "GL_UNSIGNED_SHORT_4444", + "GL_UNSIGNED_SHORT_5551", + "GL_UNSIGNED_SHORT_565" +}; + + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_es_version = 20; + + config.window_width = 320; + config.window_height = 200; + config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DEPTH; + +PIGLIT_GL_TEST_CONFIG_END + +GLuint prog; +GLuint frag; +GLuint vert; + +char vertex_shader [] = + "attribute vec4 vPosition;\n" + "void main()\n" + "{\n" + " gl_Position = vPosition;\n" + "}"; + +char fragment_shader [] = + "precision mediump float;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + "}"; + +static const struct { + GLenum format; + GLenum type; + enum piglit_result (*checkfn)(GLubyte *); + struct { + int x, y, width, height; + } coords; + int expected_error; + char *gl_error_msg; + enum _format_key format_idx; + enum _type_key type_idx; +} targets[] = { + { + GL_RGBA, + GL_UNSIGNED_BYTE, + check_buffer_is_not_changed, + { -10, -10, 10, 10 }, + 0, + "Reading from -10 -10 failed", + _RGBA, + _UNSIGNED_BYTE + }, + { + GL_RGBA, + GL_UNSIGNED_BYTE, + check_buffer_is_not_changed, + { 0, 0, 0, 0 }, + 0, + "Reading from 0 0 for 0 bytes should not copy data", + _RGBA, + _UNSIGNED_BYTE + }, + { + GL_RGBA, + GL_UNSIGNED_BYTE, + NULL, + { 0, 0, 1, 1 }, + 0, + "Reading from 0 0 to 1 1 to NULL failed", + _RGBA, + _UNSIGNED_BYTE + }, + { + GL_RGBA, + GL_UNSIGNED_BYTE, + check_buffer_is_not_changed, + { 0, 0, -10, -10 }, + GL_INVALID_VALUE, + "Neg width/height should generate GL_INVALID_VALUE", + _RGBA, + _UNSIGNED_BYTE + }, + { + GL_LUMINANCE, + GL_UNSIGNED_BYTE, + NULL, + { 0, 0, WIDTH, HEIGHT }, + GL_INVALID_OPERATION, + "GL_LUMINANCE should generate GL_INVALID_OPERATION", + _LUMINANCE, + _UNSIGNED_BYTE + }, + { + GL_LUMINANCE_ALPHA, + GL_UNSIGNED_BYTE, + NULL, + { 0, 0, WIDTH, HEIGHT }, + GL_INVALID_OPERATION, + "GL_LUMINANCE_ALPHA should generate GL_INVALID_OPERATION", + _LUMINANCE_ALPHA, + _UNSIGNED_BYTE + }, + { + GL_DEPTH_COMPONENT, + GL_UNSIGNED_BYTE, + NULL, + { 0, 0, WIDTH, HEIGHT }, + GL_INVALID_OPERATION, + "GL_DEPTH_COMPONENT should generate GL_INVALID_OPERATION", + _DEPTH_COMPONENT, + _UNSIGNED_BYTE + }, + { + 0x1800, + GL_UNSIGNED_BYTE, + NULL, + { 0, 0, WIDTH, HEIGHT }, + GL_INVALID_OPERATION, + "Invalid format value 0x1800 should generate GL_INVALID_OPERATION", + _x1800, + _UNSIGNED_BYTE + }, + { + GL_RGBA, + GL_UNSIGNED_SHORT_5_6_5, + NULL, + { 0, 0, WIDTH, HEIGHT }, + GL_INVALID_OPERATION, + "GL_RGBA & 565 should generated a GL_INVALID_OPERATION", + _RGBA, + _UNSIGNED_SHORT_565 + }, + { + GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, + check_buffer_RGB_565, + { 0, 0, WIDTH, HEIGHT }, + GL_INVALID_OPERATION, + "glReadPixels with GL_RGB & GL_UNSIGNED_SHORT_565 failed.", + _RGB, + _UNSIGNED_SHORT_565 + }, +}; + + +enum piglit_result +validate_results(void) +{ + /* pad a bit so we can do a request larger than the viewport */ + GLubyte buffer[HEIGHT+50][WIDTH][4]; + enum piglit_result final_result = PIGLIT_PASS; + int v; + + /* first make sure glError has no issues */ + if (!piglit_check_gl_error(0)) + return PIGLIT_FAIL; + + for (v = 0; v < ARRAY_SIZE(targets); v++) { + clear_buffer((GLubyte *)&buffer); + glReadPixels(targets[v].coords.x, + targets[v].coords.y, + targets[v].coords.width, + targets[v].coords.height, + targets[v].format, + targets[v].type, + &buffer); + if (!piglit_check_gl_error(targets[v].expected_error)) { + fprintf(stderr, "%s\n",targets[v].gl_error_msg); + final_result = PIGLIT_FAIL; + } + if (targets[v].checkfn) { + if (targets[v].checkfn((GLubyte *)&buffer) == PIGLIT_FAIL) { + fprintf(stderr, "%s & %s, buffer has incorrect results\n",format_strings[targets[v].format_idx], type_strings[targets[v].type_idx]); + final_result = PIGLIT_FAIL; + } + } + } + piglit_report_result(final_result); + + return final_result; +} + +void +link_and_use_shaders(void) +{ + prog = glCreateProgram(); + + vert = piglit_compile_shader_text(GL_VERTEX_SHADER, vertex_shader); + frag = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fragment_shader); + + glAttachShader(prog, vert); + glAttachShader(prog, frag); + + prog = piglit_link_simple_program(vert, frag); + if (!prog) { + piglit_report_result(PIGLIT_FAIL); + return; + } + + glDeleteShader(vert); + glDeleteShader(frag); + + glUseProgram(prog); + if (!piglit_check_gl_error(0)) { + piglit_report_result(PIGLIT_FAIL); + return; + } +} + +enum piglit_result +piglit_display(void) +{ + GLfloat vertices[] = { + 0.5, -0.5, 0.0, + 0.5, 0.5, 0.0, + -0.5, 0.5, 0.0, + -0.5, -0.5, 0.0 }; + + glClear(GL_COLOR_BUFFER_BIT); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); + glEnableVertexAttribArray(0); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + return validate_results(); +} + +void +piglit_init(int argc, char *argv[]) +{ + link_and_use_shaders(); +} diff --git a/tests/spec/gles-2.0/api/glreadpixels.c b/tests/spec/gles-2.0/api/glreadpixels.c new file mode 100644 index 0000000..0e37d87 --- /dev/null +++ b/tests/spec/gles-2.0/api/glreadpixels.c @@ -0,0 +1,293 @@ +/* + * Copyright © 2013 Linaro Inc + * + * 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 (including the next + * paragraph) 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. + */ + +/** + * This is test exercises glReadPixels + * as specified by the OpenGL ES 2.0.25 spec. + * + * Todo: GL_PACK_ALIGNMENT via glPixelStorei isn't tested + * reading from GL_COLOR_ATTACHMENT0 when the default framebuffer + * isn't bound is not tested + * combo of GL_IMPLEMENTATION_COLOR_READ_FORMAT + * GL_IMPLEMENTATION_COLOR_READ_TYPE is not tested + * add variations for DEPTH_STENCIL_OES and STENCIL_INDEX + * + * \author Tom Gall + */ + +#include +#include +#include "piglit-util-gl-common.h" +#include "glreadpixels-common.h" + + +const char *format_strings [] = { + "GL_DEPTH_COMPONENT", + "GL_ALPHA", + "GL_RGB", + "GL_RGBA", + "GL_LUMINANCE", + "GL_LUMINANCE_ALPHA", + "0x1800" +}; + +const char *type_strings[] = { + "GL_UNSIGNED_BYTE", + "GL_UNSIGNED_SHORT_4444", + "GL_UNSIGNED_SHORT_5551", + "GL_UNSIGNED_SHORT_565" +}; + + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_es_version = 20; + + config.window_width = 320; + config.window_height = 200; + config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DEPTH; + +PIGLIT_GL_TEST_CONFIG_END + +GLuint prog; +GLuint frag; +GLuint vert; + +char vertex_shader [] = + "attribute vec4 vPosition;\n" + "void main()\n" + "{\n" + " gl_Position = vPosition;\n" + "}"; + +char fragment_shader [] = + "precision mediump float;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" + "}"; + +static const struct { + GLenum format; + GLenum type; + enum piglit_result (*checkfn)(GLubyte *); + struct { + int x, y, width, height; + } coords; + int expected_error; + char *gl_error_msg; + enum _format_key format_idx; + enum _type_key type_idx; +} targets[] = { + { + GL_RGBA, + GL_UNSIGNED_BYTE, + check_buffer_RGBA, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_RGBA & GL_UNSIGNED_BTYE failed", + _RGBA, + _UNSIGNED_BYTE + }, + { + GL_RGBA, + GL_UNSIGNED_SHORT_5_5_5_1, + check_buffer_RGBA_5551, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_RGBA & 5551 failed.", + _RGBA, + _UNSIGNED_SHORT_5551 + }, + { + GL_RGBA, + GL_UNSIGNED_SHORT_4_4_4_4, + check_buffer_RGBA_4444, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_RGBA & GL_UNSIGNED_SHORT 4444 failed.", + _RGBA, + _UNSIGNED_SHORT_4444 + }, + { + GL_ALPHA, + GL_UNSIGNED_BYTE, + check_buffer_ALPHA, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_ALPHA & GL_UNSIGNED_BYTE failed.", + _ALPHA, + _UNSIGNED_BYTE + }, + { + GL_ALPHA, + GL_UNSIGNED_SHORT_5_6_5, + check_buffer_ALPHA, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_ALPHA & GL_UNSIGNED_SHORT_565 failed.", + _ALPHA, + _UNSIGNED_SHORT_565 + }, + { + GL_ALPHA, + GL_UNSIGNED_SHORT_5_5_5_1, + check_buffer_ALPHA, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_ALPHA & GL_UNSIGNED_SHORT_5551 failed.", + _ALPHA, + _UNSIGNED_SHORT_5551 + }, + { + GL_ALPHA, + GL_UNSIGNED_SHORT_4_4_4_4, + check_buffer_ALPHA, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_ALPHA & GL_UNSIGNED_SHORT_4444 failed.", + _ALPHA, + _UNSIGNED_SHORT_4444 + }, + { + GL_RGB, + GL_UNSIGNED_BYTE, + check_buffer_RGB, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_RGB & GL_UNSIGNED_BYTE failed.", + _RGB, + _UNSIGNED_BYTE + }, + { + GL_RGB, + GL_UNSIGNED_SHORT_5_5_5_1, + check_buffer_RGBA_5551, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_RGB & GL_UNSIGNED_SHORT_ 5551 failed.", + _RGB, + _UNSIGNED_SHORT_5551 + }, + { + GL_RGB, + GL_UNSIGNED_SHORT_4_4_4_4, + check_buffer_RGBA_4444, + { 0, 0, WIDTH, HEIGHT }, + 0, + "glReadPixels with GL_RGB & GL_UNSIGNED_SHORT_4444 failed.", + _RGB, + _UNSIGNED_SHORT_4444 + } +}; + + +enum piglit_result +validate_results(void) +{ + /* pad a bit so we can do a request larger than the viewport */ + GLubyte buffer[HEIGHT+50][WIDTH][4]; + enum piglit_result final_result = PIGLIT_PASS; + int v; + + /* first make sure glError has no issues */ + if (!piglit_check_gl_error(0)) + return PIGLIT_FAIL; + + for (v = 0; v < ARRAY_SIZE(targets); v++) { + clear_buffer((GLubyte *)&buffer); + glReadPixels(targets[v].coords.x, + targets[v].coords.y, + targets[v].coords.width, + targets[v].coords.height, + targets[v].format, + targets[v].type, + &buffer); + if (!piglit_check_gl_error(targets[v].expected_error)) { + fprintf(stderr, "%s\n",targets[v].gl_error_msg); + final_result = PIGLIT_FAIL; + } + if (targets[v].checkfn) { + if (targets[v].checkfn((GLubyte *)&buffer) == PIGLIT_FAIL) { + fprintf(stderr, "%s & %s, buffer has incorrect results\n", + format_strings[targets[v].format_idx], + type_strings[targets[v].type_idx]); + final_result = PIGLIT_FAIL; + } + } + } + piglit_report_result(final_result); + + return final_result; +} + +void +link_and_use_shaders(void) +{ + prog = glCreateProgram(); + + vert = piglit_compile_shader_text(GL_VERTEX_SHADER, vertex_shader); + frag = piglit_compile_shader_text(GL_FRAGMENT_SHADER, fragment_shader); + + glAttachShader(prog, vert); + glAttachShader(prog, frag); + + prog = piglit_link_simple_program(vert, frag); + if (!prog) { + piglit_report_result(PIGLIT_FAIL); + return; + } + + glDeleteShader(vert); + glDeleteShader(frag); + + glUseProgram(prog); + if (!piglit_check_gl_error(0)) { + piglit_report_result(PIGLIT_FAIL); + return; + } +} + +enum piglit_result +piglit_display(void) +{ + GLfloat vertices[] = { + 0.5, -0.5, 0.0, + 0.5, 0.5, 0.0, + -0.5, 0.5, 0.0, + -0.5, -0.5, 0.0 }; + + glClear(GL_COLOR_BUFFER_BIT); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); + glEnableVertexAttribArray(0); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + return validate_results(); +} + +void +piglit_init(int argc, char *argv[]) +{ + link_and_use_shaders(); +}