1*b7c941bbSAndroid Build Coastguard Worker /*
2*b7c941bbSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*b7c941bbSAndroid Build Coastguard Worker *
4*b7c941bbSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*b7c941bbSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*b7c941bbSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*b7c941bbSAndroid Build Coastguard Worker *
8*b7c941bbSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*b7c941bbSAndroid Build Coastguard Worker *
10*b7c941bbSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*b7c941bbSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*b7c941bbSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b7c941bbSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*b7c941bbSAndroid Build Coastguard Worker * limitations under the License.
15*b7c941bbSAndroid Build Coastguard Worker */
16*b7c941bbSAndroid Build Coastguard Worker
17*b7c941bbSAndroid Build Coastguard Worker #include <EGL/egl.h>
18*b7c941bbSAndroid Build Coastguard Worker #include <EGL/eglext.h>
19*b7c941bbSAndroid Build Coastguard Worker #include <GLES2/gl2.h>
20*b7c941bbSAndroid Build Coastguard Worker #include <GLES2/gl2ext.h>
21*b7c941bbSAndroid Build Coastguard Worker #include <jni.h>
22*b7c941bbSAndroid Build Coastguard Worker #include <stdlib.h>
23*b7c941bbSAndroid Build Coastguard Worker #include <android/hardware_buffer.h>
24*b7c941bbSAndroid Build Coastguard Worker #include <android/log.h>
25*b7c941bbSAndroid Build Coastguard Worker #include <cmath>
26*b7c941bbSAndroid Build Coastguard Worker #include <string>
27*b7c941bbSAndroid Build Coastguard Worker #include <sstream>
28*b7c941bbSAndroid Build Coastguard Worker
29*b7c941bbSAndroid Build Coastguard Worker #define LOG_TAG "VrExtensionsJni"
30*b7c941bbSAndroid Build Coastguard Worker #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE,LOG_TAG,__VA_ARGS__)
31*b7c941bbSAndroid Build Coastguard Worker
32*b7c941bbSAndroid Build Coastguard Worker using PFNEGLGETNATIVECLIENTBUFFERANDROID =
33*b7c941bbSAndroid Build Coastguard Worker EGLClientBuffer(EGLAPIENTRYP)(const AHardwareBuffer* buffer);
34*b7c941bbSAndroid Build Coastguard Worker
35*b7c941bbSAndroid Build Coastguard Worker using PFNGLEGLIMAGETARGETTEXTURE2DOESPROC = void(GL_APIENTRYP)(GLenum target,
36*b7c941bbSAndroid Build Coastguard Worker void* image);
37*b7c941bbSAndroid Build Coastguard Worker
38*b7c941bbSAndroid Build Coastguard Worker using PFNGLBUFFERSTORAGEEXTERNALEXTPROC =
39*b7c941bbSAndroid Build Coastguard Worker void(GL_APIENTRYP)(GLenum target, GLintptr offset, GLsizeiptr size,
40*b7c941bbSAndroid Build Coastguard Worker void* clientBuffer, GLbitfield flags);
41*b7c941bbSAndroid Build Coastguard Worker
42*b7c941bbSAndroid Build Coastguard Worker using PFNGLMAPBUFFERRANGEPROC = void*(GL_APIENTRYP)(GLenum target,
43*b7c941bbSAndroid Build Coastguard Worker GLintptr offset,
44*b7c941bbSAndroid Build Coastguard Worker GLsizeiptr length,
45*b7c941bbSAndroid Build Coastguard Worker GLbitfield access);
46*b7c941bbSAndroid Build Coastguard Worker
47*b7c941bbSAndroid Build Coastguard Worker using PFNGLUNMAPBUFFERPROC = void*(GL_APIENTRYP)(GLenum target);
48*b7c941bbSAndroid Build Coastguard Worker
49*b7c941bbSAndroid Build Coastguard Worker PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
50*b7c941bbSAndroid Build Coastguard Worker PFNEGLGETNATIVECLIENTBUFFERANDROID eglGetNativeClientBufferANDROID;
51*b7c941bbSAndroid Build Coastguard Worker PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
52*b7c941bbSAndroid Build Coastguard Worker PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR;
53*b7c941bbSAndroid Build Coastguard Worker PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC
54*b7c941bbSAndroid Build Coastguard Worker glFramebufferTextureMultisampleMultiviewOVR;
55*b7c941bbSAndroid Build Coastguard Worker PFNGLBUFFERSTORAGEEXTERNALEXTPROC glBufferStorageExternalEXT;
56*b7c941bbSAndroid Build Coastguard Worker PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
57*b7c941bbSAndroid Build Coastguard Worker PFNGLUNMAPBUFFERPROC glUnmapBuffer;
58*b7c941bbSAndroid Build Coastguard Worker
59*b7c941bbSAndroid Build Coastguard Worker #define NO_ERROR 0
60*b7c941bbSAndroid Build Coastguard Worker #define GL_UNIFORM_BUFFER 0x8A11
61*b7c941bbSAndroid Build Coastguard Worker
62*b7c941bbSAndroid Build Coastguard Worker // Declare flags that are added to MapBufferRange via EXT_buffer_storage.
63*b7c941bbSAndroid Build Coastguard Worker // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_buffer_storage.txt
64*b7c941bbSAndroid Build Coastguard Worker #define GL_MAP_PERSISTENT_BIT_EXT 0x0040
65*b7c941bbSAndroid Build Coastguard Worker #define GL_MAP_COHERENT_BIT_EXT 0x0080
66*b7c941bbSAndroid Build Coastguard Worker
67*b7c941bbSAndroid Build Coastguard Worker // Declare tokens added as a part of EGL_EXT_image_gl_colorspace.
68*b7c941bbSAndroid Build Coastguard Worker #define EGL_GL_COLORSPACE_DEFAULT_EXT 0x314D
69*b7c941bbSAndroid Build Coastguard Worker
70*b7c941bbSAndroid Build Coastguard Worker #define LOAD_PROC(NAME, TYPE) \
71*b7c941bbSAndroid Build Coastguard Worker NAME = reinterpret_cast<TYPE>(eglGetProcAddress(# NAME))
72*b7c941bbSAndroid Build Coastguard Worker
73*b7c941bbSAndroid Build Coastguard Worker #define ASSERT(condition, format, args...) \
74*b7c941bbSAndroid Build Coastguard Worker if (!(condition)) { \
75*b7c941bbSAndroid Build Coastguard Worker fail(env, format, ## args); \
76*b7c941bbSAndroid Build Coastguard Worker return; \
77*b7c941bbSAndroid Build Coastguard Worker }
78*b7c941bbSAndroid Build Coastguard Worker
79*b7c941bbSAndroid Build Coastguard Worker #define ASSERT_TRUE(a) \
80*b7c941bbSAndroid Build Coastguard Worker ASSERT((a), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
81*b7c941bbSAndroid Build Coastguard Worker #define ASSERT_FALSE(a) \
82*b7c941bbSAndroid Build Coastguard Worker ASSERT(!(a), "assert failed on (!" #a ") at " __FILE__ ":%d", __LINE__)
83*b7c941bbSAndroid Build Coastguard Worker #define ASSERT_EQ(a, b) \
84*b7c941bbSAndroid Build Coastguard Worker ASSERT((a) == (b), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
85*b7c941bbSAndroid Build Coastguard Worker #define ASSERT_NE(a, b) \
86*b7c941bbSAndroid Build Coastguard Worker ASSERT((a) != (b), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
87*b7c941bbSAndroid Build Coastguard Worker #define ASSERT_GT(a, b) \
88*b7c941bbSAndroid Build Coastguard Worker ASSERT((a) > (b), "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
89*b7c941bbSAndroid Build Coastguard Worker #define ASSERT_NEAR_RGBA(a, b, delta) \
90*b7c941bbSAndroid Build Coastguard Worker ASSERT(areNearRgba(a, b, delta), \
91*b7c941bbSAndroid Build Coastguard Worker "assert failed on (" #a ") at " __FILE__ ":%d", __LINE__)
92*b7c941bbSAndroid Build Coastguard Worker
areNearRgba(int32_t actual,int32_t expected,int delta)93*b7c941bbSAndroid Build Coastguard Worker bool areNearRgba(int32_t actual, int32_t expected, int delta) {
94*b7c941bbSAndroid Build Coastguard Worker for (int shift = 0; shift < 32; shift += 8) {
95*b7c941bbSAndroid Build Coastguard Worker if (std::abs((actual >> shift & 0xFF) - (expected >> shift & 0xFF)) > delta) {
96*b7c941bbSAndroid Build Coastguard Worker return false;
97*b7c941bbSAndroid Build Coastguard Worker }
98*b7c941bbSAndroid Build Coastguard Worker }
99*b7c941bbSAndroid Build Coastguard Worker return true;
100*b7c941bbSAndroid Build Coastguard Worker }
101*b7c941bbSAndroid Build Coastguard Worker
fail(JNIEnv * env,const char * format,...)102*b7c941bbSAndroid Build Coastguard Worker void fail(JNIEnv* env, const char* format, ...) {
103*b7c941bbSAndroid Build Coastguard Worker va_list args;
104*b7c941bbSAndroid Build Coastguard Worker va_start(args, format);
105*b7c941bbSAndroid Build Coastguard Worker char* msg;
106*b7c941bbSAndroid Build Coastguard Worker vasprintf(&msg, format, args);
107*b7c941bbSAndroid Build Coastguard Worker va_end(args);
108*b7c941bbSAndroid Build Coastguard Worker jclass exClass;
109*b7c941bbSAndroid Build Coastguard Worker exClass = env->FindClass("java/lang/AssertionError");
110*b7c941bbSAndroid Build Coastguard Worker jmethodID constructor =
111*b7c941bbSAndroid Build Coastguard Worker env->GetMethodID(exClass, "<init>",
112*b7c941bbSAndroid Build Coastguard Worker "(Ljava/lang/String;Ljava/lang/Throwable;)V");
113*b7c941bbSAndroid Build Coastguard Worker jstring msgStr = env->NewStringUTF(msg);
114*b7c941bbSAndroid Build Coastguard Worker jobject exception = env->NewObject(exClass, constructor, msgStr, nullptr);
115*b7c941bbSAndroid Build Coastguard Worker env->Throw(static_cast<jthrowable>(exception));
116*b7c941bbSAndroid Build Coastguard Worker free(msg);
117*b7c941bbSAndroid Build Coastguard Worker }
118*b7c941bbSAndroid Build Coastguard Worker
testEglImageArray(JNIEnv * env,AHardwareBuffer_Desc desc,int nsamples)119*b7c941bbSAndroid Build Coastguard Worker static void testEglImageArray(JNIEnv* env, AHardwareBuffer_Desc desc,
120*b7c941bbSAndroid Build Coastguard Worker int nsamples) {
121*b7c941bbSAndroid Build Coastguard Worker ASSERT_GT(desc.layers, 1);
122*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer* hwbuffer = nullptr;
123*b7c941bbSAndroid Build Coastguard Worker // If the format is unsupported and allocation fails, skip the test.
124*b7c941bbSAndroid Build Coastguard Worker if (AHardwareBuffer_allocate(&desc, &hwbuffer) != NO_ERROR) return;
125*b7c941bbSAndroid Build Coastguard Worker // Create EGLClientBuffer from the AHardwareBuffer.
126*b7c941bbSAndroid Build Coastguard Worker EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(hwbuffer);
127*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(native_buffer);
128*b7c941bbSAndroid Build Coastguard Worker // Create EGLImage from EGLClientBuffer.
129*b7c941bbSAndroid Build Coastguard Worker EGLint attrs[] = {EGL_NONE};
130*b7c941bbSAndroid Build Coastguard Worker EGLImageKHR image =
131*b7c941bbSAndroid Build Coastguard Worker eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
132*b7c941bbSAndroid Build Coastguard Worker EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs);
133*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(image);
134*b7c941bbSAndroid Build Coastguard Worker // Create OpenGL texture from the EGLImage.
135*b7c941bbSAndroid Build Coastguard Worker GLuint texid;
136*b7c941bbSAndroid Build Coastguard Worker glGenTextures(1, &texid);
137*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D_ARRAY, texid);
138*b7c941bbSAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D_ARRAY, image);
139*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
140*b7c941bbSAndroid Build Coastguard Worker // Create FBO and add multiview attachment.
141*b7c941bbSAndroid Build Coastguard Worker GLuint fboid;
142*b7c941bbSAndroid Build Coastguard Worker glGenFramebuffers(1, &fboid);
143*b7c941bbSAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, fboid);
144*b7c941bbSAndroid Build Coastguard Worker const GLint miplevel = 0;
145*b7c941bbSAndroid Build Coastguard Worker const GLint base_view = 0;
146*b7c941bbSAndroid Build Coastguard Worker const GLint num_views = desc.layers;
147*b7c941bbSAndroid Build Coastguard Worker if (nsamples == 1) {
148*b7c941bbSAndroid Build Coastguard Worker glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
149*b7c941bbSAndroid Build Coastguard Worker texid, miplevel, base_view, num_views);
150*b7c941bbSAndroid Build Coastguard Worker } else {
151*b7c941bbSAndroid Build Coastguard Worker glFramebufferTextureMultisampleMultiviewOVR(
152*b7c941bbSAndroid Build Coastguard Worker GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texid, miplevel, nsamples,
153*b7c941bbSAndroid Build Coastguard Worker base_view, num_views);
154*b7c941bbSAndroid Build Coastguard Worker }
155*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
156*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
157*b7c941bbSAndroid Build Coastguard Worker GL_FRAMEBUFFER_COMPLETE);
158*b7c941bbSAndroid Build Coastguard Worker // Release memory.
159*b7c941bbSAndroid Build Coastguard Worker glDeleteTextures(1, &texid);
160*b7c941bbSAndroid Build Coastguard Worker glDeleteFramebuffers(1, &fboid);
161*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer_release(hwbuffer);
162*b7c941bbSAndroid Build Coastguard Worker }
163*b7c941bbSAndroid Build Coastguard Worker
164*b7c941bbSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL
Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestEglImageArray(JNIEnv * env,jclass)165*b7c941bbSAndroid Build Coastguard Worker Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestEglImageArray(
166*b7c941bbSAndroid Build Coastguard Worker JNIEnv* env, jclass /* unused */) {
167*b7c941bbSAndroid Build Coastguard Worker // First, load entry points provided by extensions.
168*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glEGLImageTargetTexture2DOES,
169*b7c941bbSAndroid Build Coastguard Worker PFNGLEGLIMAGETARGETTEXTURE2DOESPROC);
170*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glEGLImageTargetTexture2DOES, nullptr);
171*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(eglGetNativeClientBufferANDROID,
172*b7c941bbSAndroid Build Coastguard Worker PFNEGLGETNATIVECLIENTBUFFERANDROID);
173*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(eglGetNativeClientBufferANDROID, nullptr);
174*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(eglCreateImageKHR, PFNEGLCREATEIMAGEKHRPROC);
175*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(eglCreateImageKHR, nullptr);
176*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glFramebufferTextureMultiviewOVR,
177*b7c941bbSAndroid Build Coastguard Worker PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC);
178*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glFramebufferTextureMultiviewOVR, nullptr);
179*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glFramebufferTextureMultisampleMultiviewOVR,
180*b7c941bbSAndroid Build Coastguard Worker PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC);
181*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glFramebufferTextureMultisampleMultiviewOVR, nullptr);
182*b7c941bbSAndroid Build Coastguard Worker // Try creating a 32x32 AHardwareBuffer and attaching it to a multiview
183*b7c941bbSAndroid Build Coastguard Worker // framebuffer, with various formats and depths.
184*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer_Desc desc = {};
185*b7c941bbSAndroid Build Coastguard Worker desc.width = 32;
186*b7c941bbSAndroid Build Coastguard Worker desc.height = 32;
187*b7c941bbSAndroid Build Coastguard Worker desc.usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
188*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
189*b7c941bbSAndroid Build Coastguard Worker const int layers[] = {2, 4};
190*b7c941bbSAndroid Build Coastguard Worker const int formats[] = {
191*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM,
192*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
193*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM,
194*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT,
195*b7c941bbSAndroid Build Coastguard Worker // Do not test AHARDWAREBUFFER_FORMAT_BLOB, it isn't color-renderable.
196*b7c941bbSAndroid Build Coastguard Worker };
197*b7c941bbSAndroid Build Coastguard Worker const int samples[] = {1, 2, 4};
198*b7c941bbSAndroid Build Coastguard Worker for (int nsamples : samples) {
199*b7c941bbSAndroid Build Coastguard Worker for (auto nlayers : layers) {
200*b7c941bbSAndroid Build Coastguard Worker for (auto format : formats) {
201*b7c941bbSAndroid Build Coastguard Worker desc.layers = nlayers;
202*b7c941bbSAndroid Build Coastguard Worker desc.format = format;
203*b7c941bbSAndroid Build Coastguard Worker testEglImageArray(env, desc, nsamples);
204*b7c941bbSAndroid Build Coastguard Worker }
205*b7c941bbSAndroid Build Coastguard Worker }
206*b7c941bbSAndroid Build Coastguard Worker }
207*b7c941bbSAndroid Build Coastguard Worker }
208*b7c941bbSAndroid Build Coastguard Worker
testExternalBuffer(JNIEnv * env,uint64_t usage,bool write_hwbuffer,const std::string & test_string)209*b7c941bbSAndroid Build Coastguard Worker static void testExternalBuffer(JNIEnv* env, uint64_t usage, bool write_hwbuffer,
210*b7c941bbSAndroid Build Coastguard Worker const std::string& test_string) {
211*b7c941bbSAndroid Build Coastguard Worker // Create a blob AHardwareBuffer suitable for holding the string.
212*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer_Desc desc = {};
213*b7c941bbSAndroid Build Coastguard Worker desc.width = test_string.size();
214*b7c941bbSAndroid Build Coastguard Worker desc.height = 1;
215*b7c941bbSAndroid Build Coastguard Worker desc.layers = 1;
216*b7c941bbSAndroid Build Coastguard Worker desc.format = AHARDWAREBUFFER_FORMAT_BLOB;
217*b7c941bbSAndroid Build Coastguard Worker desc.usage = usage;
218*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer* hwbuffer = nullptr;
219*b7c941bbSAndroid Build Coastguard Worker int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
220*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
221*b7c941bbSAndroid Build Coastguard Worker // Create EGLClientBuffer from the AHardwareBuffer.
222*b7c941bbSAndroid Build Coastguard Worker EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(hwbuffer);
223*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(native_buffer);
224*b7c941bbSAndroid Build Coastguard Worker // Create uniform buffer from EGLClientBuffer.
225*b7c941bbSAndroid Build Coastguard Worker const GLbitfield flags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
226*b7c941bbSAndroid Build Coastguard Worker GL_MAP_COHERENT_BIT_EXT | GL_MAP_PERSISTENT_BIT_EXT;
227*b7c941bbSAndroid Build Coastguard Worker GLuint buf = 0;
228*b7c941bbSAndroid Build Coastguard Worker glGenBuffers(1, &buf);
229*b7c941bbSAndroid Build Coastguard Worker glBindBuffer(GL_UNIFORM_BUFFER, buf);
230*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
231*b7c941bbSAndroid Build Coastguard Worker const GLsizeiptr bufsize = desc.width * desc.height;
232*b7c941bbSAndroid Build Coastguard Worker glBufferStorageExternalEXT(GL_UNIFORM_BUFFER, 0,
233*b7c941bbSAndroid Build Coastguard Worker bufsize, native_buffer, flags);
234*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
235*b7c941bbSAndroid Build Coastguard Worker // Obtain a writeable pointer using either OpenGL or the Android API,
236*b7c941bbSAndroid Build Coastguard Worker // then copy the test string into it.
237*b7c941bbSAndroid Build Coastguard Worker if (write_hwbuffer) {
238*b7c941bbSAndroid Build Coastguard Worker void* data = nullptr;
239*b7c941bbSAndroid Build Coastguard Worker error = AHardwareBuffer_lock(hwbuffer,
240*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_CPU_READ_RARELY, -1,
241*b7c941bbSAndroid Build Coastguard Worker NULL, &data);
242*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
243*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(data);
244*b7c941bbSAndroid Build Coastguard Worker memcpy(data, test_string.c_str(), test_string.size());
245*b7c941bbSAndroid Build Coastguard Worker error = AHardwareBuffer_unlock(hwbuffer, nullptr);
246*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
247*b7c941bbSAndroid Build Coastguard Worker } else {
248*b7c941bbSAndroid Build Coastguard Worker void* data =
249*b7c941bbSAndroid Build Coastguard Worker glMapBufferRange(GL_UNIFORM_BUFFER, 0, bufsize,
250*b7c941bbSAndroid Build Coastguard Worker GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT_EXT);
251*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
252*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(data);
253*b7c941bbSAndroid Build Coastguard Worker memcpy(data, test_string.c_str(), test_string.size());
254*b7c941bbSAndroid Build Coastguard Worker glUnmapBuffer(GL_UNIFORM_BUFFER);
255*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
256*b7c941bbSAndroid Build Coastguard Worker }
257*b7c941bbSAndroid Build Coastguard Worker // Obtain a readable pointer and verify the data.
258*b7c941bbSAndroid Build Coastguard Worker void* data = glMapBufferRange(GL_UNIFORM_BUFFER, 0, bufsize, GL_MAP_READ_BIT);
259*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(data);
260*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(strncmp(static_cast<char*>(data), test_string.c_str(),
261*b7c941bbSAndroid Build Coastguard Worker test_string.size()), 0);
262*b7c941bbSAndroid Build Coastguard Worker glUnmapBuffer(GL_UNIFORM_BUFFER);
263*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
264*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer_release(hwbuffer);
265*b7c941bbSAndroid Build Coastguard Worker }
266*b7c941bbSAndroid Build Coastguard Worker
267*b7c941bbSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL
Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestExternalBuffer(JNIEnv * env,jclass)268*b7c941bbSAndroid Build Coastguard Worker Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestExternalBuffer(
269*b7c941bbSAndroid Build Coastguard Worker JNIEnv* env, jclass /* unused */) {
270*b7c941bbSAndroid Build Coastguard Worker // First, check for EXT_external_buffer in the extension string.
271*b7c941bbSAndroid Build Coastguard Worker auto exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
272*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(exts);
273*b7c941bbSAndroid Build Coastguard Worker if (strstr(exts, "GL_EXT_external_buffer") == nullptr) return;
274*b7c941bbSAndroid Build Coastguard Worker // Next, load entry points provided by extensions.
275*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(eglGetNativeClientBufferANDROID, PFNEGLGETNATIVECLIENTBUFFERANDROID);
276*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(eglGetNativeClientBufferANDROID, nullptr);
277*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glBufferStorageExternalEXT, PFNGLBUFFERSTORAGEEXTERNALEXTPROC);
278*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glBufferStorageExternalEXT, nullptr);
279*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glMapBufferRange, PFNGLMAPBUFFERRANGEPROC);
280*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glMapBufferRange, nullptr);
281*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glUnmapBuffer, PFNGLUNMAPBUFFERPROC);
282*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glUnmapBuffer, nullptr);
283*b7c941bbSAndroid Build Coastguard Worker const uint64_t usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN |
284*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_CPU_READ_RARELY |
285*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER |
286*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA;
287*b7c941bbSAndroid Build Coastguard Worker const std::string test_string = "Hello, world.";
288*b7c941bbSAndroid Build Coastguard Worker // First try writing to the buffer using OpenGL, then try writing to it via
289*b7c941bbSAndroid Build Coastguard Worker // the AHardwareBuffer API.
290*b7c941bbSAndroid Build Coastguard Worker testExternalBuffer(env, usage, false, test_string);
291*b7c941bbSAndroid Build Coastguard Worker testExternalBuffer(env, usage, true, test_string);
292*b7c941bbSAndroid Build Coastguard Worker }
293*b7c941bbSAndroid Build Coastguard Worker
294*b7c941bbSAndroid Build Coastguard Worker const GLchar* const kSrgbVertexCode = R"(
295*b7c941bbSAndroid Build Coastguard Worker // vertex position in clip space (-1..1)
296*b7c941bbSAndroid Build Coastguard Worker attribute vec4 position;
297*b7c941bbSAndroid Build Coastguard Worker varying mediump vec2 uv;
298*b7c941bbSAndroid Build Coastguard Worker void main() {
299*b7c941bbSAndroid Build Coastguard Worker gl_Position = position;
300*b7c941bbSAndroid Build Coastguard Worker uv = vec2(0.5 * (position.x + 1.0), 0.5);
301*b7c941bbSAndroid Build Coastguard Worker })";
302*b7c941bbSAndroid Build Coastguard Worker
303*b7c941bbSAndroid Build Coastguard Worker const GLchar* const kSrgbFragmentCode = R"(
304*b7c941bbSAndroid Build Coastguard Worker varying mediump vec2 uv;
305*b7c941bbSAndroid Build Coastguard Worker uniform sampler2D tex;
306*b7c941bbSAndroid Build Coastguard Worker void main() {
307*b7c941bbSAndroid Build Coastguard Worker gl_FragColor = texture2D(tex, uv);
308*b7c941bbSAndroid Build Coastguard Worker })";
309*b7c941bbSAndroid Build Coastguard Worker
SrgbChannelToLinear(float cs)310*b7c941bbSAndroid Build Coastguard Worker static inline float SrgbChannelToLinear(float cs) {
311*b7c941bbSAndroid Build Coastguard Worker if (cs <= 0.04045)
312*b7c941bbSAndroid Build Coastguard Worker return cs / 12.92f;
313*b7c941bbSAndroid Build Coastguard Worker else
314*b7c941bbSAndroid Build Coastguard Worker return std::pow((cs + 0.055f) / 1.055f, 2.4f);
315*b7c941bbSAndroid Build Coastguard Worker }
316*b7c941bbSAndroid Build Coastguard Worker
LinearChannelToSrgb(float cs)317*b7c941bbSAndroid Build Coastguard Worker static inline float LinearChannelToSrgb(float cs) {
318*b7c941bbSAndroid Build Coastguard Worker if (cs <= 0.0f)
319*b7c941bbSAndroid Build Coastguard Worker return 0.0f;
320*b7c941bbSAndroid Build Coastguard Worker else if (cs < 0.0031308f)
321*b7c941bbSAndroid Build Coastguard Worker return 12.92f * cs;
322*b7c941bbSAndroid Build Coastguard Worker else if (cs < 1.0f)
323*b7c941bbSAndroid Build Coastguard Worker return 1.055f * std::pow(cs, 0.41666f) - 0.055f;
324*b7c941bbSAndroid Build Coastguard Worker else
325*b7c941bbSAndroid Build Coastguard Worker return 1.0f;
326*b7c941bbSAndroid Build Coastguard Worker }
327*b7c941bbSAndroid Build Coastguard Worker
SrgbColorToLinear(uint32_t color)328*b7c941bbSAndroid Build Coastguard Worker static uint32_t SrgbColorToLinear(uint32_t color) {
329*b7c941bbSAndroid Build Coastguard Worker float r = SrgbChannelToLinear((color & 0xff) / 255.0f);
330*b7c941bbSAndroid Build Coastguard Worker float g = SrgbChannelToLinear(((color >> 8) & 0xff) / 255.0f);
331*b7c941bbSAndroid Build Coastguard Worker float b = SrgbChannelToLinear(((color >> 16) & 0xff) / 255.0f);
332*b7c941bbSAndroid Build Coastguard Worker uint32_t r8 = r * 255.0f;
333*b7c941bbSAndroid Build Coastguard Worker uint32_t g8 = g * 255.0f;
334*b7c941bbSAndroid Build Coastguard Worker uint32_t b8 = b * 255.0f;
335*b7c941bbSAndroid Build Coastguard Worker uint32_t a8 = color >> 24;
336*b7c941bbSAndroid Build Coastguard Worker return (a8 << 24) | (b8 << 16) | (g8 << 8) | r8;
337*b7c941bbSAndroid Build Coastguard Worker }
338*b7c941bbSAndroid Build Coastguard Worker
LinearColorToSrgb(uint32_t color)339*b7c941bbSAndroid Build Coastguard Worker static uint32_t LinearColorToSrgb(uint32_t color) {
340*b7c941bbSAndroid Build Coastguard Worker float r = LinearChannelToSrgb((color & 0xff) / 255.0f);
341*b7c941bbSAndroid Build Coastguard Worker float g = LinearChannelToSrgb(((color >> 8) & 0xff) / 255.0f);
342*b7c941bbSAndroid Build Coastguard Worker float b = LinearChannelToSrgb(((color >> 16) & 0xff) / 255.0f);
343*b7c941bbSAndroid Build Coastguard Worker uint32_t r8 = r * 255.0f;
344*b7c941bbSAndroid Build Coastguard Worker uint32_t g8 = g * 255.0f;
345*b7c941bbSAndroid Build Coastguard Worker uint32_t b8 = b * 255.0f;
346*b7c941bbSAndroid Build Coastguard Worker uint32_t a8 = color >> 24;
347*b7c941bbSAndroid Build Coastguard Worker return (a8 << 24) | (b8 << 16) | (g8 << 8) | r8;
348*b7c941bbSAndroid Build Coastguard Worker }
349*b7c941bbSAndroid Build Coastguard Worker
LerpColor(uint32_t color0,uint32_t color1,float t)350*b7c941bbSAndroid Build Coastguard Worker static uint32_t LerpColor(uint32_t color0, uint32_t color1, float t) {
351*b7c941bbSAndroid Build Coastguard Worker float r0 = (color0 & 0xff) / 255.0f;
352*b7c941bbSAndroid Build Coastguard Worker float g0 = ((color0 >> 8) & 0xff) / 255.0f;
353*b7c941bbSAndroid Build Coastguard Worker float b0 = ((color0 >> 16) & 0xff) / 255.0f;
354*b7c941bbSAndroid Build Coastguard Worker float a0 = ((color0 >> 24) & 0xff) / 255.0f;
355*b7c941bbSAndroid Build Coastguard Worker float r1 = (color1 & 0xff) / 255.0f;
356*b7c941bbSAndroid Build Coastguard Worker float g1 = ((color1 >> 8) & 0xff) / 255.0f;
357*b7c941bbSAndroid Build Coastguard Worker float b1 = ((color1 >> 16) & 0xff) / 255.0f;
358*b7c941bbSAndroid Build Coastguard Worker float a1 = ((color1 >> 24) & 0xff) / 255.0f;
359*b7c941bbSAndroid Build Coastguard Worker uint32_t r8 = (r0 * (1.0f - t) + r1 * t) * 255.0f;
360*b7c941bbSAndroid Build Coastguard Worker uint32_t g8 = (g0 * (1.0f - t) + g1 * t) * 255.0f;
361*b7c941bbSAndroid Build Coastguard Worker uint32_t b8 = (b0 * (1.0f - t) + b1 * t) * 255.0f;
362*b7c941bbSAndroid Build Coastguard Worker uint32_t a8 = (a0 * (1.0f - t) + a1 * t) * 255.0f;
363*b7c941bbSAndroid Build Coastguard Worker return (a8 << 24) | (b8 << 16) | (g8 << 8) | r8;
364*b7c941bbSAndroid Build Coastguard Worker }
365*b7c941bbSAndroid Build Coastguard Worker
366*b7c941bbSAndroid Build Coastguard Worker // Choose an odd-numbered framebuffer width so that we can
367*b7c941bbSAndroid Build Coastguard Worker // extract the middle pixel of a gradient.
368*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kFramebufferWidth = 31;
369*b7c941bbSAndroid Build Coastguard Worker
370*b7c941bbSAndroid Build Coastguard Worker // Declare the pixel data for the 2x1 texture.
371*b7c941bbSAndroid Build Coastguard Worker // Color components are ordered like this: AABBGGRR
372*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kTextureData[] = {
373*b7c941bbSAndroid Build Coastguard Worker 0xff800000, // Half-Blue
374*b7c941bbSAndroid Build Coastguard Worker 0xff000080, // Half-Red
375*b7c941bbSAndroid Build Coastguard Worker };
376*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kTextureWidth = sizeof(kTextureData) / sizeof(kTextureData[0]);
377*b7c941bbSAndroid Build Coastguard Worker
378*b7c941bbSAndroid Build Coastguard Worker // Declare expected values for the middle pixel for various sampling behaviors.
379*b7c941bbSAndroid Build Coastguard Worker const uint32_t kExpectedMiddlePixel_NoSrgb = LerpColor(kTextureData[0], kTextureData[1], 0.5f);
380*b7c941bbSAndroid Build Coastguard Worker const uint32_t kExpectedMiddlePixel_LinearizeAfterFiltering =
381*b7c941bbSAndroid Build Coastguard Worker SrgbColorToLinear(kExpectedMiddlePixel_NoSrgb);
382*b7c941bbSAndroid Build Coastguard Worker const uint32_t kExpectedMiddlePixel_LinearizeBeforeFiltering =
383*b7c941bbSAndroid Build Coastguard Worker LerpColor(SrgbColorToLinear(kTextureData[0]), SrgbColorToLinear(kTextureData[1]), 0.5f);
384*b7c941bbSAndroid Build Coastguard Worker
385*b7c941bbSAndroid Build Coastguard Worker // Declare expected values for the final pixel color for various blending behaviors.
386*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kBlendDestColor = 0xff000080;
387*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kBlendSourceColor = 0x80800000;
388*b7c941bbSAndroid Build Coastguard Worker const uint32_t kExpectedBlendedPixel_NoSrgb = LerpColor(kBlendSourceColor, kBlendDestColor, 0.5f);
389*b7c941bbSAndroid Build Coastguard Worker const uint32_t kExpectedBlendedPixel_Srgb =
390*b7c941bbSAndroid Build Coastguard Worker LinearColorToSrgb(LerpColor(kBlendSourceColor, SrgbColorToLinear(kBlendDestColor), 0.5f));
391*b7c941bbSAndroid Build Coastguard Worker
392*b7c941bbSAndroid Build Coastguard Worker // Define a set of test flags. Not using an enum to avoid lots of casts.
393*b7c941bbSAndroid Build Coastguard Worker namespace SrgbFlag {
394*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kHardwareBuffer = 1 << 0;
395*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kSrgbFormat = 1 << 1;
396*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kEglColorspaceDefault = 1 << 2;
397*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kEglColorspaceLinear = 1 << 3;
398*b7c941bbSAndroid Build Coastguard Worker constexpr uint32_t kEglColorspaceSrgb = 1 << 4;
399*b7c941bbSAndroid Build Coastguard Worker } // namespace SrgbFlag
400*b7c941bbSAndroid Build Coastguard Worker
configureEglColorspace(EGLint attrs[4],uint32_t srgb_flags)401*b7c941bbSAndroid Build Coastguard Worker static void configureEglColorspace(EGLint attrs[4], uint32_t srgb_flags) {
402*b7c941bbSAndroid Build Coastguard Worker if (srgb_flags & SrgbFlag::kEglColorspaceDefault) {
403*b7c941bbSAndroid Build Coastguard Worker attrs[0] = EGL_GL_COLORSPACE_KHR;
404*b7c941bbSAndroid Build Coastguard Worker attrs[1] = EGL_GL_COLORSPACE_DEFAULT_EXT;
405*b7c941bbSAndroid Build Coastguard Worker } else if (srgb_flags & SrgbFlag::kEglColorspaceLinear) {
406*b7c941bbSAndroid Build Coastguard Worker attrs[0] = EGL_GL_COLORSPACE_KHR;
407*b7c941bbSAndroid Build Coastguard Worker attrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
408*b7c941bbSAndroid Build Coastguard Worker } else if (srgb_flags & SrgbFlag::kEglColorspaceSrgb) {
409*b7c941bbSAndroid Build Coastguard Worker attrs[0] = EGL_GL_COLORSPACE_KHR;
410*b7c941bbSAndroid Build Coastguard Worker attrs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
411*b7c941bbSAndroid Build Coastguard Worker } else {
412*b7c941bbSAndroid Build Coastguard Worker attrs[0] = EGL_NONE;
413*b7c941bbSAndroid Build Coastguard Worker attrs[1] = EGL_NONE;
414*b7c941bbSAndroid Build Coastguard Worker }
415*b7c941bbSAndroid Build Coastguard Worker attrs[2] = EGL_NONE;
416*b7c941bbSAndroid Build Coastguard Worker attrs[3] = EGL_NONE;
417*b7c941bbSAndroid Build Coastguard Worker }
418*b7c941bbSAndroid Build Coastguard Worker
printSrgbFlags(std::ostream & out,uint32_t srgb_flags)419*b7c941bbSAndroid Build Coastguard Worker static void printSrgbFlags(std::ostream& out, uint32_t srgb_flags) {
420*b7c941bbSAndroid Build Coastguard Worker if (srgb_flags & SrgbFlag::kHardwareBuffer) {
421*b7c941bbSAndroid Build Coastguard Worker out << " AHardwareBuffer";
422*b7c941bbSAndroid Build Coastguard Worker }
423*b7c941bbSAndroid Build Coastguard Worker if (srgb_flags & SrgbFlag::kSrgbFormat) {
424*b7c941bbSAndroid Build Coastguard Worker out << " GL_SRGB_ALPHA";
425*b7c941bbSAndroid Build Coastguard Worker }
426*b7c941bbSAndroid Build Coastguard Worker if (srgb_flags & SrgbFlag::kEglColorspaceDefault) {
427*b7c941bbSAndroid Build Coastguard Worker out << " EGL_GL_COLORSPACE_DEFAULT_KHR";
428*b7c941bbSAndroid Build Coastguard Worker }
429*b7c941bbSAndroid Build Coastguard Worker if (srgb_flags & SrgbFlag::kEglColorspaceLinear) {
430*b7c941bbSAndroid Build Coastguard Worker out << " EGL_GL_COLORSPACE_LINEAR_KHR";
431*b7c941bbSAndroid Build Coastguard Worker }
432*b7c941bbSAndroid Build Coastguard Worker if (srgb_flags & SrgbFlag::kEglColorspaceSrgb) {
433*b7c941bbSAndroid Build Coastguard Worker out << " EGL_GL_COLORSPACE_SRGB_KHR";
434*b7c941bbSAndroid Build Coastguard Worker }
435*b7c941bbSAndroid Build Coastguard Worker }
436*b7c941bbSAndroid Build Coastguard Worker
437*b7c941bbSAndroid Build Coastguard Worker // Draws a gradient and extracts the middle pixel. Returns void to allow ASSERT to work.
testLinearMagnification(JNIEnv * env,uint32_t flags,uint32_t * middle_pixel)438*b7c941bbSAndroid Build Coastguard Worker static void testLinearMagnification(JNIEnv* env, uint32_t flags, uint32_t* middle_pixel) {
439*b7c941bbSAndroid Build Coastguard Worker const bool use_hwbuffer = flags & SrgbFlag::kHardwareBuffer;
440*b7c941bbSAndroid Build Coastguard Worker const bool use_srgb_format = flags & SrgbFlag::kSrgbFormat;
441*b7c941bbSAndroid Build Coastguard Worker GLuint srgbtex;
442*b7c941bbSAndroid Build Coastguard Worker glGenTextures(1, &srgbtex);
443*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, srgbtex);
444*b7c941bbSAndroid Build Coastguard Worker if (use_hwbuffer) {
445*b7c941bbSAndroid Build Coastguard Worker // Create a one-dimensional AHardwareBuffer.
446*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer_Desc desc = {};
447*b7c941bbSAndroid Build Coastguard Worker desc.width = kTextureWidth;
448*b7c941bbSAndroid Build Coastguard Worker desc.height = 1;
449*b7c941bbSAndroid Build Coastguard Worker desc.layers = 1;
450*b7c941bbSAndroid Build Coastguard Worker desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
451*b7c941bbSAndroid Build Coastguard Worker desc.usage =
452*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
453*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer* hwbuffer = nullptr;
454*b7c941bbSAndroid Build Coastguard Worker int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
455*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
456*b7c941bbSAndroid Build Coastguard Worker // Populate the pixels.
457*b7c941bbSAndroid Build Coastguard Worker uint32_t* pixels = nullptr;
458*b7c941bbSAndroid Build Coastguard Worker error = AHardwareBuffer_lock(hwbuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN, -1, nullptr,
459*b7c941bbSAndroid Build Coastguard Worker reinterpret_cast<void**>(&pixels));
460*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
461*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(pixels);
462*b7c941bbSAndroid Build Coastguard Worker memcpy(pixels, kTextureData, sizeof(kTextureData));
463*b7c941bbSAndroid Build Coastguard Worker error = AHardwareBuffer_unlock(hwbuffer, nullptr);
464*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
465*b7c941bbSAndroid Build Coastguard Worker // Create EGLClientBuffer from the AHardwareBuffer.
466*b7c941bbSAndroid Build Coastguard Worker EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(hwbuffer);
467*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(native_buffer);
468*b7c941bbSAndroid Build Coastguard Worker // Create EGLImage from EGLClientBuffer.
469*b7c941bbSAndroid Build Coastguard Worker EGLint attrs[4];
470*b7c941bbSAndroid Build Coastguard Worker configureEglColorspace(attrs, flags);
471*b7c941bbSAndroid Build Coastguard Worker EGLImageKHR image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
472*b7c941bbSAndroid Build Coastguard Worker EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs);
473*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(image);
474*b7c941bbSAndroid Build Coastguard Worker // Allocate the OpenGL texture using the EGLImage.
475*b7c941bbSAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
476*b7c941bbSAndroid Build Coastguard Worker } else {
477*b7c941bbSAndroid Build Coastguard Worker GLenum internal_format = use_srgb_format ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8_OES;
478*b7c941bbSAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, internal_format, kTextureWidth, 1, 0, GL_RGBA,
479*b7c941bbSAndroid Build Coastguard Worker GL_UNSIGNED_BYTE, kTextureData);
480*b7c941bbSAndroid Build Coastguard Worker }
481*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
482*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
483*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
484*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
485*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
486*b7c941bbSAndroid Build Coastguard Worker // Clear to an interesting constant color to make it easier to spot bugs.
487*b7c941bbSAndroid Build Coastguard Worker glClearColor(1.0, 0.0, 0.5, 0.25);
488*b7c941bbSAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
489*b7c941bbSAndroid Build Coastguard Worker // Draw the texture.
490*b7c941bbSAndroid Build Coastguard Worker const float kTriangleCoords[] = {-1, -1, -1, 1, 1, -1, 1, 1};
491*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, srgbtex);
492*b7c941bbSAndroid Build Coastguard Worker const int kPositionSlot = 0;
493*b7c941bbSAndroid Build Coastguard Worker glVertexAttribPointer(kPositionSlot, 2, GL_FLOAT, false, 0, kTriangleCoords);
494*b7c941bbSAndroid Build Coastguard Worker glEnableVertexAttribArray(kPositionSlot);
495*b7c941bbSAndroid Build Coastguard Worker glViewport(0, 0, kFramebufferWidth, 1);
496*b7c941bbSAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
497*b7c941bbSAndroid Build Coastguard Worker // Read back the framebuffer.
498*b7c941bbSAndroid Build Coastguard Worker glReadPixels(kFramebufferWidth / 2, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, middle_pixel);
499*b7c941bbSAndroid Build Coastguard Worker std::ostringstream flag_string;
500*b7c941bbSAndroid Build Coastguard Worker printSrgbFlags(flag_string, flags);
501*b7c941bbSAndroid Build Coastguard Worker LOGV("Filtered Result: %8.8X Flags =%s", *middle_pixel, flag_string.str().c_str());
502*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
503*b7c941bbSAndroid Build Coastguard Worker }
504*b7c941bbSAndroid Build Coastguard Worker
505*b7c941bbSAndroid Build Coastguard Worker // Blends a color into an (optionally) sRGB-encoded framebuffer and extracts the final color.
506*b7c941bbSAndroid Build Coastguard Worker // Returns void to allow ASSERT to work.
testFramebufferBlending(JNIEnv * env,uint32_t flags,uint32_t * final_color)507*b7c941bbSAndroid Build Coastguard Worker static void testFramebufferBlending(JNIEnv* env, uint32_t flags, uint32_t* final_color) {
508*b7c941bbSAndroid Build Coastguard Worker const bool use_hwbuffer = flags & SrgbFlag::kHardwareBuffer;
509*b7c941bbSAndroid Build Coastguard Worker const bool use_srgb_format = flags & SrgbFlag::kSrgbFormat;
510*b7c941bbSAndroid Build Coastguard Worker const bool override_egl_colorspace = use_hwbuffer && (flags & SrgbFlag::kEglColorspaceSrgb);
511*b7c941bbSAndroid Build Coastguard Worker GLuint tex;
512*b7c941bbSAndroid Build Coastguard Worker glGenTextures(1, &tex);
513*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, tex);
514*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
515*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
516*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
517*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
518*b7c941bbSAndroid Build Coastguard Worker // Create a 1x1 half-blue, half-opaque texture.
519*b7c941bbSAndroid Build Coastguard Worker const uint32_t kTextureData[] = {
520*b7c941bbSAndroid Build Coastguard Worker kBlendSourceColor,
521*b7c941bbSAndroid Build Coastguard Worker };
522*b7c941bbSAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
523*b7c941bbSAndroid Build Coastguard Worker GL_UNSIGNED_BYTE, kTextureData);
524*b7c941bbSAndroid Build Coastguard Worker // Create 1x1 framebuffer object.
525*b7c941bbSAndroid Build Coastguard Worker GLuint fbo;
526*b7c941bbSAndroid Build Coastguard Worker glGenFramebuffers(1, &fbo);
527*b7c941bbSAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, fbo);
528*b7c941bbSAndroid Build Coastguard Worker GLuint fbotex;
529*b7c941bbSAndroid Build Coastguard Worker glGenTextures(1, &fbotex);
530*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, fbotex);
531*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
532*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
533*b7c941bbSAndroid Build Coastguard Worker if (use_hwbuffer) {
534*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer_Desc desc = {};
535*b7c941bbSAndroid Build Coastguard Worker desc.width = 1;
536*b7c941bbSAndroid Build Coastguard Worker desc.height = 1;
537*b7c941bbSAndroid Build Coastguard Worker desc.layers = 1;
538*b7c941bbSAndroid Build Coastguard Worker desc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
539*b7c941bbSAndroid Build Coastguard Worker desc.usage =
540*b7c941bbSAndroid Build Coastguard Worker AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE | AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
541*b7c941bbSAndroid Build Coastguard Worker AHardwareBuffer* hwbuffer = nullptr;
542*b7c941bbSAndroid Build Coastguard Worker int error = AHardwareBuffer_allocate(&desc, &hwbuffer);
543*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(error, NO_ERROR);
544*b7c941bbSAndroid Build Coastguard Worker // Create EGLClientBuffer from the AHardwareBuffer.
545*b7c941bbSAndroid Build Coastguard Worker EGLClientBuffer native_buffer = eglGetNativeClientBufferANDROID(hwbuffer);
546*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(native_buffer);
547*b7c941bbSAndroid Build Coastguard Worker // Create EGLImage from EGLClientBuffer.
548*b7c941bbSAndroid Build Coastguard Worker EGLint attrs[4];
549*b7c941bbSAndroid Build Coastguard Worker configureEglColorspace(attrs, flags);
550*b7c941bbSAndroid Build Coastguard Worker EGLImageKHR image = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
551*b7c941bbSAndroid Build Coastguard Worker EGL_NATIVE_BUFFER_ANDROID, native_buffer, attrs);
552*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(image);
553*b7c941bbSAndroid Build Coastguard Worker // Allocate the OpenGL texture using the EGLImage.
554*b7c941bbSAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
555*b7c941bbSAndroid Build Coastguard Worker } else {
556*b7c941bbSAndroid Build Coastguard Worker GLenum internal_format = use_srgb_format ? GL_SRGB8_ALPHA8_EXT : GL_RGBA8_OES;
557*b7c941bbSAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, internal_format, 1, 1, 0, GL_RGBA,
558*b7c941bbSAndroid Build Coastguard Worker GL_UNSIGNED_BYTE, nullptr);
559*b7c941bbSAndroid Build Coastguard Worker }
560*b7c941bbSAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
561*b7c941bbSAndroid Build Coastguard Worker GL_TEXTURE_2D, fbotex, 0);
562*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
563*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
564*b7c941bbSAndroid Build Coastguard Worker // Clear to half-red.
565*b7c941bbSAndroid Build Coastguard Worker if (use_srgb_format || override_egl_colorspace) {
566*b7c941bbSAndroid Build Coastguard Worker glClearColor(SrgbChannelToLinear(0.5), 0.0, 0.0, 1.0);
567*b7c941bbSAndroid Build Coastguard Worker } else {
568*b7c941bbSAndroid Build Coastguard Worker glClearColor(0.5, 0.0, 0.0, 1.0);
569*b7c941bbSAndroid Build Coastguard Worker }
570*b7c941bbSAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT);
571*b7c941bbSAndroid Build Coastguard Worker // Sanity check the cleared color.
572*b7c941bbSAndroid Build Coastguard Worker uint32_t cleared_color = 0;
573*b7c941bbSAndroid Build Coastguard Worker glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &cleared_color);
574*b7c941bbSAndroid Build Coastguard Worker LOGV(" Cleared Color: %8.8X", cleared_color);
575*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(cleared_color, kBlendDestColor, 1);
576*b7c941bbSAndroid Build Coastguard Worker // Draw the texture.
577*b7c941bbSAndroid Build Coastguard Worker glEnable(GL_BLEND);
578*b7c941bbSAndroid Build Coastguard Worker glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
579*b7c941bbSAndroid Build Coastguard Worker const float kTriangleCoords[] = {-1, -1, -1, 1, 1, -1, 1, 1};
580*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, tex);
581*b7c941bbSAndroid Build Coastguard Worker const int kPositionSlot = 0;
582*b7c941bbSAndroid Build Coastguard Worker glVertexAttribPointer(kPositionSlot, 2, GL_FLOAT, false, 0, kTriangleCoords);
583*b7c941bbSAndroid Build Coastguard Worker glEnableVertexAttribArray(kPositionSlot);
584*b7c941bbSAndroid Build Coastguard Worker glViewport(0, 0, 1, 1);
585*b7c941bbSAndroid Build Coastguard Worker glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
586*b7c941bbSAndroid Build Coastguard Worker // Read back the framebuffer.
587*b7c941bbSAndroid Build Coastguard Worker glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, final_color);
588*b7c941bbSAndroid Build Coastguard Worker std::ostringstream flag_string;
589*b7c941bbSAndroid Build Coastguard Worker printSrgbFlags(flag_string, flags);
590*b7c941bbSAndroid Build Coastguard Worker LOGV("Blending Result: %8.8X Flags =%s", *final_color, flag_string.str().c_str());
591*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
592*b7c941bbSAndroid Build Coastguard Worker }
593*b7c941bbSAndroid Build Coastguard Worker
594*b7c941bbSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL
Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestSrgbBuffer(JNIEnv * env,jclass)595*b7c941bbSAndroid Build Coastguard Worker Java_android_vr_cts_VrExtensionBehaviorTest_nativeTestSrgbBuffer(
596*b7c941bbSAndroid Build Coastguard Worker JNIEnv* env, jclass /* unused */) {
597*b7c941bbSAndroid Build Coastguard Worker // First, check the published extension strings against expectations.
598*b7c941bbSAndroid Build Coastguard Worker const char *egl_exts =
599*b7c941bbSAndroid Build Coastguard Worker eglQueryString(eglGetCurrentDisplay(), EGL_EXTENSIONS);
600*b7c941bbSAndroid Build Coastguard Worker LOGV("EGL Extensions: %s", egl_exts);
601*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(egl_exts);
602*b7c941bbSAndroid Build Coastguard Worker bool egl_colorspace_supported = strstr(egl_exts, "EGL_EXT_image_gl_colorspace");
603*b7c941bbSAndroid Build Coastguard Worker auto gl_exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
604*b7c941bbSAndroid Build Coastguard Worker LOGV("OpenGL Extensions: %s", gl_exts);
605*b7c941bbSAndroid Build Coastguard Worker ASSERT_TRUE(gl_exts);
606*b7c941bbSAndroid Build Coastguard Worker // Load ancillary entry points provided by extensions.
607*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(eglGetNativeClientBufferANDROID,
608*b7c941bbSAndroid Build Coastguard Worker PFNEGLGETNATIVECLIENTBUFFERANDROID);
609*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(eglGetNativeClientBufferANDROID, nullptr);
610*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(eglCreateImageKHR, PFNEGLCREATEIMAGEKHRPROC);
611*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(eglCreateImageKHR, nullptr);
612*b7c941bbSAndroid Build Coastguard Worker LOAD_PROC(glEGLImageTargetTexture2DOES,
613*b7c941bbSAndroid Build Coastguard Worker PFNGLEGLIMAGETARGETTEXTURE2DOESPROC);
614*b7c941bbSAndroid Build Coastguard Worker ASSERT_NE(glEGLImageTargetTexture2DOES, nullptr);
615*b7c941bbSAndroid Build Coastguard Worker // Create a plain old one-dimensional FBO to render to.
616*b7c941bbSAndroid Build Coastguard Worker GLuint fbo;
617*b7c941bbSAndroid Build Coastguard Worker glGenFramebuffers(1, &fbo);
618*b7c941bbSAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, fbo);
619*b7c941bbSAndroid Build Coastguard Worker GLuint fbotex;
620*b7c941bbSAndroid Build Coastguard Worker glGenTextures(1, &fbotex);
621*b7c941bbSAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, fbotex);
622*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
623*b7c941bbSAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
624*b7c941bbSAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kFramebufferWidth, 1, 0, GL_RGBA,
625*b7c941bbSAndroid Build Coastguard Worker GL_UNSIGNED_BYTE, nullptr);
626*b7c941bbSAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
627*b7c941bbSAndroid Build Coastguard Worker GL_TEXTURE_2D, fbotex, 0);
628*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
629*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
630*b7c941bbSAndroid Build Coastguard Worker // Compile and link shaders.
631*b7c941bbSAndroid Build Coastguard Worker int program = glCreateProgram();
632*b7c941bbSAndroid Build Coastguard Worker int vshader = glCreateShader(GL_VERTEX_SHADER);
633*b7c941bbSAndroid Build Coastguard Worker glShaderSource(vshader, 1, &kSrgbVertexCode, nullptr);
634*b7c941bbSAndroid Build Coastguard Worker glCompileShader(vshader);
635*b7c941bbSAndroid Build Coastguard Worker glAttachShader(program, vshader);
636*b7c941bbSAndroid Build Coastguard Worker int fshader = glCreateShader(GL_FRAGMENT_SHADER);
637*b7c941bbSAndroid Build Coastguard Worker glShaderSource(fshader, 1, &kSrgbFragmentCode, nullptr);
638*b7c941bbSAndroid Build Coastguard Worker glCompileShader(fshader);
639*b7c941bbSAndroid Build Coastguard Worker glAttachShader(program, fshader);
640*b7c941bbSAndroid Build Coastguard Worker glLinkProgram(program);
641*b7c941bbSAndroid Build Coastguard Worker int status;
642*b7c941bbSAndroid Build Coastguard Worker glGetProgramiv(program, GL_LINK_STATUS, &status);
643*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(status, GL_TRUE);
644*b7c941bbSAndroid Build Coastguard Worker glUseProgram(program);
645*b7c941bbSAndroid Build Coastguard Worker ASSERT_EQ(glGetError(), GL_NO_ERROR);
646*b7c941bbSAndroid Build Coastguard Worker
647*b7c941bbSAndroid Build Coastguard Worker // Filtering test.
648*b7c941bbSAndroid Build Coastguard Worker LOGV("Expected value for NoSrgb = %8.8X", kExpectedMiddlePixel_NoSrgb);
649*b7c941bbSAndroid Build Coastguard Worker LOGV("Expected value for Srgb = %8.8X", kExpectedMiddlePixel_LinearizeBeforeFiltering);
650*b7c941bbSAndroid Build Coastguard Worker uint32_t middle_pixel;
651*b7c941bbSAndroid Build Coastguard Worker // First do a sanity check with plain old pre-linearized textures.
652*b7c941bbSAndroid Build Coastguard Worker testLinearMagnification(env, 0, &middle_pixel);
653*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
654*b7c941bbSAndroid Build Coastguard Worker testLinearMagnification(env, SrgbFlag::kHardwareBuffer, &middle_pixel);
655*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
656*b7c941bbSAndroid Build Coastguard Worker // Try a "normally allocated" OpenGL texture with an sRGB source format.
657*b7c941bbSAndroid Build Coastguard Worker testLinearMagnification(env, SrgbFlag::kSrgbFormat, &middle_pixel);
658*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(middle_pixel, kExpectedMiddlePixel_LinearizeBeforeFiltering, 1);
659*b7c941bbSAndroid Build Coastguard Worker // Try EGL_EXT_image_gl_colorspace.
660*b7c941bbSAndroid Build Coastguard Worker if (egl_colorspace_supported) {
661*b7c941bbSAndroid Build Coastguard Worker testLinearMagnification(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceDefault, &middle_pixel);
662*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
663*b7c941bbSAndroid Build Coastguard Worker testLinearMagnification(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceLinear, &middle_pixel);
664*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(middle_pixel, kExpectedMiddlePixel_NoSrgb, 1);
665*b7c941bbSAndroid Build Coastguard Worker testLinearMagnification(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceSrgb, &middle_pixel);
666*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(middle_pixel, kExpectedMiddlePixel_LinearizeBeforeFiltering, 1);
667*b7c941bbSAndroid Build Coastguard Worker }
668*b7c941bbSAndroid Build Coastguard Worker
669*b7c941bbSAndroid Build Coastguard Worker // Blending test.
670*b7c941bbSAndroid Build Coastguard Worker LOGV("Expected value for NoSrgb = %8.8X", kExpectedBlendedPixel_NoSrgb);
671*b7c941bbSAndroid Build Coastguard Worker LOGV("Expected value for Srgb = %8.8X", kExpectedBlendedPixel_Srgb);
672*b7c941bbSAndroid Build Coastguard Worker uint32_t final_color;
673*b7c941bbSAndroid Build Coastguard Worker // First do a sanity check with plain old pre-linearized textures.
674*b7c941bbSAndroid Build Coastguard Worker testFramebufferBlending(env, 0, &final_color);
675*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(final_color, kExpectedBlendedPixel_NoSrgb, 1);
676*b7c941bbSAndroid Build Coastguard Worker testFramebufferBlending(env, SrgbFlag::kHardwareBuffer, &final_color);
677*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(final_color, kExpectedBlendedPixel_NoSrgb, 1);
678*b7c941bbSAndroid Build Coastguard Worker // Try a "normally allocated" OpenGL texture with an sRGB source format.
679*b7c941bbSAndroid Build Coastguard Worker testFramebufferBlending(env, SrgbFlag::kSrgbFormat, &final_color);
680*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(final_color, kExpectedBlendedPixel_Srgb, 1);
681*b7c941bbSAndroid Build Coastguard Worker // Try EGL_EXT_image_gl_colorspace.
682*b7c941bbSAndroid Build Coastguard Worker if (egl_colorspace_supported) {
683*b7c941bbSAndroid Build Coastguard Worker testFramebufferBlending(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceDefault, &final_color);
684*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(final_color, kExpectedBlendedPixel_NoSrgb, 1);
685*b7c941bbSAndroid Build Coastguard Worker testFramebufferBlending(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceLinear, &final_color);
686*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(final_color, kExpectedBlendedPixel_NoSrgb, 1);
687*b7c941bbSAndroid Build Coastguard Worker testFramebufferBlending(env, SrgbFlag::kHardwareBuffer | SrgbFlag::kEglColorspaceSrgb, &final_color);
688*b7c941bbSAndroid Build Coastguard Worker ASSERT_NEAR_RGBA(final_color, kExpectedBlendedPixel_Srgb, 1);
689*b7c941bbSAndroid Build Coastguard Worker }
690*b7c941bbSAndroid Build Coastguard Worker }
691