1*8975f5c5SAndroid Build Coastguard Worker// 2*8975f5c5SAndroid Build Coastguard Worker// Copyright 2021 The ANGLE Project Authors. All rights reserved. 3*8975f5c5SAndroid Build Coastguard Worker// Use of this source code is governed by a BSD-style license that can be 4*8975f5c5SAndroid Build Coastguard Worker// found in the LICENSE file. 5*8975f5c5SAndroid Build Coastguard Worker// 6*8975f5c5SAndroid Build Coastguard Worker// ImageTestMetal: 7*8975f5c5SAndroid Build Coastguard Worker// Tests the correctness of eglImage with native Metal texture extensions. 8*8975f5c5SAndroid Build Coastguard Worker// 9*8975f5c5SAndroid Build Coastguard Worker 10*8975f5c5SAndroid Build Coastguard Worker#include "test_utils/ANGLETest.h" 11*8975f5c5SAndroid Build Coastguard Worker 12*8975f5c5SAndroid Build Coastguard Worker#include "common/mathutil.h" 13*8975f5c5SAndroid Build Coastguard Worker#include "test_utils/gl_raii.h" 14*8975f5c5SAndroid Build Coastguard Worker#include "util/EGLWindow.h" 15*8975f5c5SAndroid Build Coastguard Worker 16*8975f5c5SAndroid Build Coastguard Worker#include <CoreFoundation/CoreFoundation.h> 17*8975f5c5SAndroid Build Coastguard Worker#include <Metal/Metal.h> 18*8975f5c5SAndroid Build Coastguard Worker#include <gmock/gmock.h> 19*8975f5c5SAndroid Build Coastguard Worker#include <span> 20*8975f5c5SAndroid Build Coastguard Worker 21*8975f5c5SAndroid Build Coastguard Workernamespace angle 22*8975f5c5SAndroid Build Coastguard Worker{ 23*8975f5c5SAndroid Build Coastguard Workernamespace 24*8975f5c5SAndroid Build Coastguard Worker{ 25*8975f5c5SAndroid Build Coastguard Workerconstexpr char kOESExt[] = "GL_OES_EGL_image"; 26*8975f5c5SAndroid Build Coastguard Workerconstexpr char kBaseExt[] = "EGL_KHR_image_base"; 27*8975f5c5SAndroid Build Coastguard Workerconstexpr char kDeviceMtlExt[] = "EGL_ANGLE_device_metal"; 28*8975f5c5SAndroid Build Coastguard Workerconstexpr char kEGLMtlImageNativeTextureExt[] = "EGL_ANGLE_metal_texture_client_buffer"; 29*8975f5c5SAndroid Build Coastguard Workerconstexpr EGLint kDefaultAttribs[] = { 30*8975f5c5SAndroid Build Coastguard Worker EGL_NONE, 31*8975f5c5SAndroid Build Coastguard Worker}; 32*8975f5c5SAndroid Build Coastguard Worker 33*8975f5c5SAndroid Build Coastguard Workertemplate <typename T> 34*8975f5c5SAndroid Build Coastguard Workerclass ScopedMetalObjectRef : angle::NonCopyable 35*8975f5c5SAndroid Build Coastguard Worker{ 36*8975f5c5SAndroid Build Coastguard Worker public: 37*8975f5c5SAndroid Build Coastguard Worker ScopedMetalObjectRef() = default; 38*8975f5c5SAndroid Build Coastguard Worker 39*8975f5c5SAndroid Build Coastguard Worker explicit ScopedMetalObjectRef(T &&surface) : mObject(surface) {} 40*8975f5c5SAndroid Build Coastguard Worker 41*8975f5c5SAndroid Build Coastguard Worker ~ScopedMetalObjectRef() 42*8975f5c5SAndroid Build Coastguard Worker { 43*8975f5c5SAndroid Build Coastguard Worker if (mObject) 44*8975f5c5SAndroid Build Coastguard Worker { 45*8975f5c5SAndroid Build Coastguard Worker release(); 46*8975f5c5SAndroid Build Coastguard Worker mObject = nil; 47*8975f5c5SAndroid Build Coastguard Worker } 48*8975f5c5SAndroid Build Coastguard Worker } 49*8975f5c5SAndroid Build Coastguard Worker 50*8975f5c5SAndroid Build Coastguard Worker T get() const { return mObject; } 51*8975f5c5SAndroid Build Coastguard Worker 52*8975f5c5SAndroid Build Coastguard Worker operator bool() const { return !!mObject; } 53*8975f5c5SAndroid Build Coastguard Worker 54*8975f5c5SAndroid Build Coastguard Worker // auto cast to T 55*8975f5c5SAndroid Build Coastguard Worker operator T() const { return mObject; } 56*8975f5c5SAndroid Build Coastguard Worker ScopedMetalObjectRef(const ScopedMetalObjectRef &other) 57*8975f5c5SAndroid Build Coastguard Worker { 58*8975f5c5SAndroid Build Coastguard Worker if (mObject) 59*8975f5c5SAndroid Build Coastguard Worker { 60*8975f5c5SAndroid Build Coastguard Worker release(); 61*8975f5c5SAndroid Build Coastguard Worker } 62*8975f5c5SAndroid Build Coastguard Worker mObject = other.mObject; 63*8975f5c5SAndroid Build Coastguard Worker } 64*8975f5c5SAndroid Build Coastguard Worker 65*8975f5c5SAndroid Build Coastguard Worker explicit ScopedMetalObjectRef(ScopedMetalObjectRef &&other) 66*8975f5c5SAndroid Build Coastguard Worker { 67*8975f5c5SAndroid Build Coastguard Worker if (mObject) 68*8975f5c5SAndroid Build Coastguard Worker { 69*8975f5c5SAndroid Build Coastguard Worker release(); 70*8975f5c5SAndroid Build Coastguard Worker } 71*8975f5c5SAndroid Build Coastguard Worker mObject = other.mObject; 72*8975f5c5SAndroid Build Coastguard Worker other.mObject = nil; 73*8975f5c5SAndroid Build Coastguard Worker } 74*8975f5c5SAndroid Build Coastguard Worker 75*8975f5c5SAndroid Build Coastguard Worker ScopedMetalObjectRef &operator=(ScopedMetalObjectRef &&other) 76*8975f5c5SAndroid Build Coastguard Worker { 77*8975f5c5SAndroid Build Coastguard Worker if (mObject) 78*8975f5c5SAndroid Build Coastguard Worker { 79*8975f5c5SAndroid Build Coastguard Worker release(); 80*8975f5c5SAndroid Build Coastguard Worker } 81*8975f5c5SAndroid Build Coastguard Worker mObject = other.mObject; 82*8975f5c5SAndroid Build Coastguard Worker other.mObject = nil; 83*8975f5c5SAndroid Build Coastguard Worker 84*8975f5c5SAndroid Build Coastguard Worker return *this; 85*8975f5c5SAndroid Build Coastguard Worker } 86*8975f5c5SAndroid Build Coastguard Worker 87*8975f5c5SAndroid Build Coastguard Worker ScopedMetalObjectRef &operator=(const ScopedMetalObjectRef &other) 88*8975f5c5SAndroid Build Coastguard Worker { 89*8975f5c5SAndroid Build Coastguard Worker if (mObject) 90*8975f5c5SAndroid Build Coastguard Worker { 91*8975f5c5SAndroid Build Coastguard Worker release(); 92*8975f5c5SAndroid Build Coastguard Worker } 93*8975f5c5SAndroid Build Coastguard Worker mObject = other.mObject; 94*8975f5c5SAndroid Build Coastguard Worker 95*8975f5c5SAndroid Build Coastguard Worker return *this; 96*8975f5c5SAndroid Build Coastguard Worker } 97*8975f5c5SAndroid Build Coastguard Worker 98*8975f5c5SAndroid Build Coastguard Worker private: 99*8975f5c5SAndroid Build Coastguard Worker void release() 100*8975f5c5SAndroid Build Coastguard Worker { 101*8975f5c5SAndroid Build Coastguard Worker#if !__has_feature(objc_arc) 102*8975f5c5SAndroid Build Coastguard Worker [mObject release]; 103*8975f5c5SAndroid Build Coastguard Worker#endif 104*8975f5c5SAndroid Build Coastguard Worker } 105*8975f5c5SAndroid Build Coastguard Worker 106*8975f5c5SAndroid Build Coastguard Worker T mObject = nil; 107*8975f5c5SAndroid Build Coastguard Worker}; 108*8975f5c5SAndroid Build Coastguard Worker 109*8975f5c5SAndroid Build Coastguard Workerusing ScopedMetalTextureRef = ScopedMetalObjectRef<id<MTLTexture>>; 110*8975f5c5SAndroid Build Coastguard Workerusing ScopedMetalBufferRef = ScopedMetalObjectRef<id<MTLBuffer>>; 111*8975f5c5SAndroid Build Coastguard Workerusing ScopedMetalCommandQueueRef = ScopedMetalObjectRef<id<MTLCommandQueue>>; 112*8975f5c5SAndroid Build Coastguard Worker 113*8975f5c5SAndroid Build Coastguard Worker} // anonymous namespace 114*8975f5c5SAndroid Build Coastguard Worker 115*8975f5c5SAndroid Build Coastguard Workerbool IsDepthOrStencil(MTLPixelFormat format) 116*8975f5c5SAndroid Build Coastguard Worker{ 117*8975f5c5SAndroid Build Coastguard Worker switch (format) 118*8975f5c5SAndroid Build Coastguard Worker { 119*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatDepth16Unorm: 120*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatDepth32Float: 121*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatStencil8: 122*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatDepth24Unorm_Stencil8: 123*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatDepth32Float_Stencil8: 124*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatX32_Stencil8: 125*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatX24_Stencil8: 126*8975f5c5SAndroid Build Coastguard Worker return true; 127*8975f5c5SAndroid Build Coastguard Worker 128*8975f5c5SAndroid Build Coastguard Worker default: 129*8975f5c5SAndroid Build Coastguard Worker return false; 130*8975f5c5SAndroid Build Coastguard Worker } 131*8975f5c5SAndroid Build Coastguard Worker} 132*8975f5c5SAndroid Build Coastguard Worker 133*8975f5c5SAndroid Build Coastguard WorkerScopedMetalTextureRef CreateMetalTexture2D(id<MTLDevice> deviceMtl, 134*8975f5c5SAndroid Build Coastguard Worker int width, 135*8975f5c5SAndroid Build Coastguard Worker int height, 136*8975f5c5SAndroid Build Coastguard Worker MTLPixelFormat format, 137*8975f5c5SAndroid Build Coastguard Worker int arrayLength) 138*8975f5c5SAndroid Build Coastguard Worker{ 139*8975f5c5SAndroid Build Coastguard Worker @autoreleasepool 140*8975f5c5SAndroid Build Coastguard Worker { 141*8975f5c5SAndroid Build Coastguard Worker MTLTextureDescriptor *desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format 142*8975f5c5SAndroid Build Coastguard Worker width:width 143*8975f5c5SAndroid Build Coastguard Worker height:width 144*8975f5c5SAndroid Build Coastguard Worker mipmapped:NO]; 145*8975f5c5SAndroid Build Coastguard Worker desc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget; 146*8975f5c5SAndroid Build Coastguard Worker if (IsDepthOrStencil(format)) 147*8975f5c5SAndroid Build Coastguard Worker { 148*8975f5c5SAndroid Build Coastguard Worker desc.storageMode = MTLStorageModePrivate; 149*8975f5c5SAndroid Build Coastguard Worker } 150*8975f5c5SAndroid Build Coastguard Worker if (arrayLength) 151*8975f5c5SAndroid Build Coastguard Worker { 152*8975f5c5SAndroid Build Coastguard Worker desc.arrayLength = arrayLength; 153*8975f5c5SAndroid Build Coastguard Worker desc.textureType = MTLTextureType2DArray; 154*8975f5c5SAndroid Build Coastguard Worker } 155*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef re([deviceMtl newTextureWithDescriptor:desc]); 156*8975f5c5SAndroid Build Coastguard Worker return re; 157*8975f5c5SAndroid Build Coastguard Worker } 158*8975f5c5SAndroid Build Coastguard Worker} 159*8975f5c5SAndroid Build Coastguard Worker 160*8975f5c5SAndroid Build Coastguard Workerid<MTLSharedEvent> CreateMetalSharedEvent(id<MTLDevice> deviceMtl) 161*8975f5c5SAndroid Build Coastguard Worker{ 162*8975f5c5SAndroid Build Coastguard Worker id<MTLSharedEvent> sharedEvent = [deviceMtl newSharedEvent]; 163*8975f5c5SAndroid Build Coastguard Worker sharedEvent.label = @"TestSharedEvent"; 164*8975f5c5SAndroid Build Coastguard Worker return sharedEvent; 165*8975f5c5SAndroid Build Coastguard Worker} 166*8975f5c5SAndroid Build Coastguard Worker 167*8975f5c5SAndroid Build Coastguard WorkerEGLSync CreateEGLSyncFromMetalSharedEvent(EGLDisplay display, 168*8975f5c5SAndroid Build Coastguard Worker id<MTLSharedEvent> sharedEvent, 169*8975f5c5SAndroid Build Coastguard Worker uint64_t signalValue, 170*8975f5c5SAndroid Build Coastguard Worker bool signaled) 171*8975f5c5SAndroid Build Coastguard Worker{ 172*8975f5c5SAndroid Build Coastguard Worker EGLAttrib signalValueHi = signalValue >> 32; 173*8975f5c5SAndroid Build Coastguard Worker EGLAttrib signalValueLo = signalValue & 0xffffffff; 174*8975f5c5SAndroid Build Coastguard Worker std::vector<EGLAttrib> syncAttribs = { 175*8975f5c5SAndroid Build Coastguard Worker EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE, reinterpret_cast<EGLAttrib>(sharedEvent), 176*8975f5c5SAndroid Build Coastguard Worker EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_HI_ANGLE, signalValueHi, 177*8975f5c5SAndroid Build Coastguard Worker EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_LO_ANGLE, signalValueLo}; 178*8975f5c5SAndroid Build Coastguard Worker 179*8975f5c5SAndroid Build Coastguard Worker if (signaled) 180*8975f5c5SAndroid Build Coastguard Worker { 181*8975f5c5SAndroid Build Coastguard Worker syncAttribs.push_back(EGL_SYNC_CONDITION); 182*8975f5c5SAndroid Build Coastguard Worker syncAttribs.push_back(EGL_SYNC_METAL_SHARED_EVENT_SIGNALED_ANGLE); 183*8975f5c5SAndroid Build Coastguard Worker } 184*8975f5c5SAndroid Build Coastguard Worker 185*8975f5c5SAndroid Build Coastguard Worker syncAttribs.push_back(EGL_NONE); 186*8975f5c5SAndroid Build Coastguard Worker 187*8975f5c5SAndroid Build Coastguard Worker EGLSync syncWithSharedEvent = 188*8975f5c5SAndroid Build Coastguard Worker eglCreateSync(display, EGL_SYNC_METAL_SHARED_EVENT_ANGLE, syncAttribs.data()); 189*8975f5c5SAndroid Build Coastguard Worker EXPECT_NE(syncWithSharedEvent, EGL_NO_SYNC); 190*8975f5c5SAndroid Build Coastguard Worker 191*8975f5c5SAndroid Build Coastguard Worker return syncWithSharedEvent; 192*8975f5c5SAndroid Build Coastguard Worker} 193*8975f5c5SAndroid Build Coastguard Worker 194*8975f5c5SAndroid Build Coastguard Workerclass ImageTestMetal : public ANGLETest<> 195*8975f5c5SAndroid Build Coastguard Worker{ 196*8975f5c5SAndroid Build Coastguard Worker protected: 197*8975f5c5SAndroid Build Coastguard Worker ImageTestMetal() 198*8975f5c5SAndroid Build Coastguard Worker { 199*8975f5c5SAndroid Build Coastguard Worker setWindowWidth(128); 200*8975f5c5SAndroid Build Coastguard Worker setWindowHeight(128); 201*8975f5c5SAndroid Build Coastguard Worker setConfigRedBits(8); 202*8975f5c5SAndroid Build Coastguard Worker setConfigGreenBits(8); 203*8975f5c5SAndroid Build Coastguard Worker setConfigBlueBits(8); 204*8975f5c5SAndroid Build Coastguard Worker setConfigAlphaBits(8); 205*8975f5c5SAndroid Build Coastguard Worker setConfigDepthBits(24); 206*8975f5c5SAndroid Build Coastguard Worker } 207*8975f5c5SAndroid Build Coastguard Worker 208*8975f5c5SAndroid Build Coastguard Worker void testSetUp() override 209*8975f5c5SAndroid Build Coastguard Worker { 210*8975f5c5SAndroid Build Coastguard Worker constexpr char kVS[] = "precision highp float;\n" 211*8975f5c5SAndroid Build Coastguard Worker "attribute vec4 position;\n" 212*8975f5c5SAndroid Build Coastguard Worker "varying vec2 texcoord;\n" 213*8975f5c5SAndroid Build Coastguard Worker "\n" 214*8975f5c5SAndroid Build Coastguard Worker "void main()\n" 215*8975f5c5SAndroid Build Coastguard Worker "{\n" 216*8975f5c5SAndroid Build Coastguard Worker " gl_Position = position;\n" 217*8975f5c5SAndroid Build Coastguard Worker " texcoord = (position.xy * 0.5) + 0.5;\n" 218*8975f5c5SAndroid Build Coastguard Worker " texcoord.y = 1.0 - texcoord.y;\n" 219*8975f5c5SAndroid Build Coastguard Worker "}\n"; 220*8975f5c5SAndroid Build Coastguard Worker 221*8975f5c5SAndroid Build Coastguard Worker constexpr char kTextureFS[] = "precision highp float;\n" 222*8975f5c5SAndroid Build Coastguard Worker "uniform sampler2D tex;\n" 223*8975f5c5SAndroid Build Coastguard Worker "varying vec2 texcoord;\n" 224*8975f5c5SAndroid Build Coastguard Worker "\n" 225*8975f5c5SAndroid Build Coastguard Worker "void main()\n" 226*8975f5c5SAndroid Build Coastguard Worker "{\n" 227*8975f5c5SAndroid Build Coastguard Worker " gl_FragColor = texture2D(tex, texcoord);\n" 228*8975f5c5SAndroid Build Coastguard Worker "}\n"; 229*8975f5c5SAndroid Build Coastguard Worker 230*8975f5c5SAndroid Build Coastguard Worker mTextureProgram = CompileProgram(kVS, kTextureFS); 231*8975f5c5SAndroid Build Coastguard Worker if (mTextureProgram == 0) 232*8975f5c5SAndroid Build Coastguard Worker { 233*8975f5c5SAndroid Build Coastguard Worker FAIL() << "shader compilation failed."; 234*8975f5c5SAndroid Build Coastguard Worker } 235*8975f5c5SAndroid Build Coastguard Worker 236*8975f5c5SAndroid Build Coastguard Worker mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex"); 237*8975f5c5SAndroid Build Coastguard Worker 238*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR(); 239*8975f5c5SAndroid Build Coastguard Worker } 240*8975f5c5SAndroid Build Coastguard Worker 241*8975f5c5SAndroid Build Coastguard Worker void testTearDown() override { glDeleteProgram(mTextureProgram); } 242*8975f5c5SAndroid Build Coastguard Worker 243*8975f5c5SAndroid Build Coastguard Worker id<MTLDevice> getMtlDevice() 244*8975f5c5SAndroid Build Coastguard Worker { 245*8975f5c5SAndroid Build Coastguard Worker EGLAttrib angleDevice = 0; 246*8975f5c5SAndroid Build Coastguard Worker EGLAttrib device = 0; 247*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_TRUE( 248*8975f5c5SAndroid Build Coastguard Worker eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice)); 249*8975f5c5SAndroid Build Coastguard Worker 250*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), 251*8975f5c5SAndroid Build Coastguard Worker EGL_METAL_DEVICE_ANGLE, &device)); 252*8975f5c5SAndroid Build Coastguard Worker 253*8975f5c5SAndroid Build Coastguard Worker return (__bridge id<MTLDevice>)reinterpret_cast<void *>(device); 254*8975f5c5SAndroid Build Coastguard Worker } 255*8975f5c5SAndroid Build Coastguard Worker 256*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef createMtlTexture2D(int width, int height, MTLPixelFormat format) 257*8975f5c5SAndroid Build Coastguard Worker { 258*8975f5c5SAndroid Build Coastguard Worker id<MTLDevice> device = getMtlDevice(); 259*8975f5c5SAndroid Build Coastguard Worker 260*8975f5c5SAndroid Build Coastguard Worker return CreateMetalTexture2D(device, width, height, format, 0); 261*8975f5c5SAndroid Build Coastguard Worker } 262*8975f5c5SAndroid Build Coastguard Worker 263*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef createMtlTexture2DArray(int width, 264*8975f5c5SAndroid Build Coastguard Worker int height, 265*8975f5c5SAndroid Build Coastguard Worker int arrayLength, 266*8975f5c5SAndroid Build Coastguard Worker MTLPixelFormat format) 267*8975f5c5SAndroid Build Coastguard Worker { 268*8975f5c5SAndroid Build Coastguard Worker id<MTLDevice> device = getMtlDevice(); 269*8975f5c5SAndroid Build Coastguard Worker 270*8975f5c5SAndroid Build Coastguard Worker return CreateMetalTexture2D(device, width, height, format, arrayLength); 271*8975f5c5SAndroid Build Coastguard Worker } 272*8975f5c5SAndroid Build Coastguard Worker 273*8975f5c5SAndroid Build Coastguard Worker void getTextureSliceBytes(id<MTLTexture> texture, 274*8975f5c5SAndroid Build Coastguard Worker unsigned bytesPerRow, 275*8975f5c5SAndroid Build Coastguard Worker MTLRegion region, 276*8975f5c5SAndroid Build Coastguard Worker unsigned mipmapLevel, 277*8975f5c5SAndroid Build Coastguard Worker unsigned slice, 278*8975f5c5SAndroid Build Coastguard Worker std::span<uint8_t> sliceImage) 279*8975f5c5SAndroid Build Coastguard Worker { 280*8975f5c5SAndroid Build Coastguard Worker @autoreleasepool 281*8975f5c5SAndroid Build Coastguard Worker { 282*8975f5c5SAndroid Build Coastguard Worker id<MTLDevice> device = texture.device; 283*8975f5c5SAndroid Build Coastguard Worker ScopedMetalBufferRef readBuffer([device 284*8975f5c5SAndroid Build Coastguard Worker newBufferWithLength:sliceImage.size() 285*8975f5c5SAndroid Build Coastguard Worker options:MTLResourceStorageModeShared]); 286*8975f5c5SAndroid Build Coastguard Worker ScopedMetalCommandQueueRef commandQueue([device newCommandQueue]); 287*8975f5c5SAndroid Build Coastguard Worker id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer]; 288*8975f5c5SAndroid Build Coastguard Worker id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder]; 289*8975f5c5SAndroid Build Coastguard Worker [blitEncoder copyFromTexture:texture 290*8975f5c5SAndroid Build Coastguard Worker sourceSlice:slice 291*8975f5c5SAndroid Build Coastguard Worker sourceLevel:mipmapLevel 292*8975f5c5SAndroid Build Coastguard Worker sourceOrigin:region.origin 293*8975f5c5SAndroid Build Coastguard Worker sourceSize:region.size 294*8975f5c5SAndroid Build Coastguard Worker toBuffer:readBuffer 295*8975f5c5SAndroid Build Coastguard Worker destinationOffset:0 296*8975f5c5SAndroid Build Coastguard Worker destinationBytesPerRow:bytesPerRow 297*8975f5c5SAndroid Build Coastguard Worker destinationBytesPerImage:sliceImage.size()]; 298*8975f5c5SAndroid Build Coastguard Worker [blitEncoder endEncoding]; 299*8975f5c5SAndroid Build Coastguard Worker [commandBuffer commit]; 300*8975f5c5SAndroid Build Coastguard Worker [commandBuffer waitUntilCompleted]; 301*8975f5c5SAndroid Build Coastguard Worker memcpy(sliceImage.data(), readBuffer.get().contents, sliceImage.size()); 302*8975f5c5SAndroid Build Coastguard Worker } 303*8975f5c5SAndroid Build Coastguard Worker } 304*8975f5c5SAndroid Build Coastguard Worker void sourceMetalTarget2D_helper(GLubyte data[4], 305*8975f5c5SAndroid Build Coastguard Worker const EGLint *attribs, 306*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR *imageOut, 307*8975f5c5SAndroid Build Coastguard Worker GLuint *textureOut); 308*8975f5c5SAndroid Build Coastguard Worker 309*8975f5c5SAndroid Build Coastguard Worker void verifyResultsTexture(GLuint texture, 310*8975f5c5SAndroid Build Coastguard Worker const GLubyte data[4], 311*8975f5c5SAndroid Build Coastguard Worker GLenum textureTarget, 312*8975f5c5SAndroid Build Coastguard Worker GLuint program, 313*8975f5c5SAndroid Build Coastguard Worker GLuint textureUniform) 314*8975f5c5SAndroid Build Coastguard Worker { 315*8975f5c5SAndroid Build Coastguard Worker // Draw a quad with the target texture 316*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program); 317*8975f5c5SAndroid Build Coastguard Worker glBindTexture(textureTarget, texture); 318*8975f5c5SAndroid Build Coastguard Worker glUniform1i(textureUniform, 0); 319*8975f5c5SAndroid Build Coastguard Worker 320*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, "position", 0.5f); 321*8975f5c5SAndroid Build Coastguard Worker 322*8975f5c5SAndroid Build Coastguard Worker // Expect that the rendered quad has the same color as the source texture 323*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_NEAR(0, 0, data[0], data[1], data[2], data[3], 1.0); 324*8975f5c5SAndroid Build Coastguard Worker } 325*8975f5c5SAndroid Build Coastguard Worker 326*8975f5c5SAndroid Build Coastguard Worker void verifyResults2D(GLuint texture, const GLubyte data[4]) 327*8975f5c5SAndroid Build Coastguard Worker { 328*8975f5c5SAndroid Build Coastguard Worker verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram, 329*8975f5c5SAndroid Build Coastguard Worker mTextureUniformLocation); 330*8975f5c5SAndroid Build Coastguard Worker } 331*8975f5c5SAndroid Build Coastguard Worker 332*8975f5c5SAndroid Build Coastguard Worker void drawColorQuad(GLColor color) 333*8975f5c5SAndroid Build Coastguard Worker { 334*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor()); 335*8975f5c5SAndroid Build Coastguard Worker glUseProgram(program); 336*8975f5c5SAndroid Build Coastguard Worker GLint colorUniformLocation = 337*8975f5c5SAndroid Build Coastguard Worker glGetUniformLocation(program, angle::essl1_shaders::ColorUniform()); 338*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(colorUniformLocation, -1); 339*8975f5c5SAndroid Build Coastguard Worker glUniform4fv(colorUniformLocation, 1, color.toNormalizedVector().data()); 340*8975f5c5SAndroid Build Coastguard Worker drawQuad(program, essl1_shaders::PositionAttrib(), 0); 341*8975f5c5SAndroid Build Coastguard Worker glUseProgram(0); 342*8975f5c5SAndroid Build Coastguard Worker } 343*8975f5c5SAndroid Build Coastguard Worker 344*8975f5c5SAndroid Build Coastguard Worker bool hasDepth24Stencil8PixelFormat() 345*8975f5c5SAndroid Build Coastguard Worker { 346*8975f5c5SAndroid Build Coastguard Worker id<MTLDevice> device = getMtlDevice(); 347*8975f5c5SAndroid Build Coastguard Worker return device.depth24Stencil8PixelFormatSupported; 348*8975f5c5SAndroid Build Coastguard Worker } 349*8975f5c5SAndroid Build Coastguard Worker 350*8975f5c5SAndroid Build Coastguard Worker bool hasImageNativeMetalTextureExt() const 351*8975f5c5SAndroid Build Coastguard Worker { 352*8975f5c5SAndroid Build Coastguard Worker if (!IsMetal()) 353*8975f5c5SAndroid Build Coastguard Worker { 354*8975f5c5SAndroid Build Coastguard Worker return false; 355*8975f5c5SAndroid Build Coastguard Worker } 356*8975f5c5SAndroid Build Coastguard Worker EGLAttrib angleDevice = 0; 357*8975f5c5SAndroid Build Coastguard Worker eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice); 358*8975f5c5SAndroid Build Coastguard Worker if (!angleDevice) 359*8975f5c5SAndroid Build Coastguard Worker { 360*8975f5c5SAndroid Build Coastguard Worker return false; 361*8975f5c5SAndroid Build Coastguard Worker } 362*8975f5c5SAndroid Build Coastguard Worker auto extensionString = static_cast<const char *>( 363*8975f5c5SAndroid Build Coastguard Worker eglQueryDeviceStringEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_EXTENSIONS)); 364*8975f5c5SAndroid Build Coastguard Worker if (strstr(extensionString, kDeviceMtlExt) == nullptr) 365*8975f5c5SAndroid Build Coastguard Worker { 366*8975f5c5SAndroid Build Coastguard Worker return false; 367*8975f5c5SAndroid Build Coastguard Worker } 368*8975f5c5SAndroid Build Coastguard Worker return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), 369*8975f5c5SAndroid Build Coastguard Worker kEGLMtlImageNativeTextureExt); 370*8975f5c5SAndroid Build Coastguard Worker } 371*8975f5c5SAndroid Build Coastguard Worker 372*8975f5c5SAndroid Build Coastguard Worker bool hasOESExt() const { return IsGLExtensionEnabled(kOESExt); } 373*8975f5c5SAndroid Build Coastguard Worker 374*8975f5c5SAndroid Build Coastguard Worker bool hasBaseExt() const 375*8975f5c5SAndroid Build Coastguard Worker { 376*8975f5c5SAndroid Build Coastguard Worker return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kBaseExt); 377*8975f5c5SAndroid Build Coastguard Worker } 378*8975f5c5SAndroid Build Coastguard Worker 379*8975f5c5SAndroid Build Coastguard Worker GLuint mTextureProgram; 380*8975f5c5SAndroid Build Coastguard Worker GLint mTextureUniformLocation; 381*8975f5c5SAndroid Build Coastguard Worker}; 382*8975f5c5SAndroid Build Coastguard Worker 383*8975f5c5SAndroid Build Coastguard Workervoid ImageTestMetal::sourceMetalTarget2D_helper(GLubyte data[4], 384*8975f5c5SAndroid Build Coastguard Worker const EGLint *attribs, 385*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR *imageOut, 386*8975f5c5SAndroid Build Coastguard Worker GLuint *textureOut) 387*8975f5c5SAndroid Build Coastguard Worker{ 388*8975f5c5SAndroid Build Coastguard Worker EGLWindow *window = getEGLWindow(); 389*8975f5c5SAndroid Build Coastguard Worker 390*8975f5c5SAndroid Build Coastguard Worker // Create MTLTexture 391*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = createMtlTexture2D(1, 1, MTLPixelFormatRGBA8Unorm); 392*8975f5c5SAndroid Build Coastguard Worker 393*8975f5c5SAndroid Build Coastguard Worker // Create image 394*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 395*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 396*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 397*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 398*8975f5c5SAndroid Build Coastguard Worker 399*8975f5c5SAndroid Build Coastguard Worker // Write the data to the MTLTexture 400*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 401*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 402*8975f5c5SAndroid Build Coastguard Worker slice:0 403*8975f5c5SAndroid Build Coastguard Worker withBytes:data 404*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 405*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:0]; 406*8975f5c5SAndroid Build Coastguard Worker 407*8975f5c5SAndroid Build Coastguard Worker // Create a texture target to bind the egl image 408*8975f5c5SAndroid Build Coastguard Worker GLuint target; 409*8975f5c5SAndroid Build Coastguard Worker glGenTextures(1, &target); 410*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, target); 411*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 412*8975f5c5SAndroid Build Coastguard Worker 413*8975f5c5SAndroid Build Coastguard Worker *imageOut = image; 414*8975f5c5SAndroid Build Coastguard Worker *textureOut = target; 415*8975f5c5SAndroid Build Coastguard Worker} 416*8975f5c5SAndroid Build Coastguard Worker 417*8975f5c5SAndroid Build Coastguard Worker// Testing source metal EGL image, target 2D texture 418*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, SourceMetalTarget2D) 419*8975f5c5SAndroid Build Coastguard Worker{ 420*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 421*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 422*8975f5c5SAndroid Build Coastguard Worker 423*8975f5c5SAndroid Build Coastguard Worker EGLWindow *window = getEGLWindow(); 424*8975f5c5SAndroid Build Coastguard Worker 425*8975f5c5SAndroid Build Coastguard Worker // Create the Image 426*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image; 427*8975f5c5SAndroid Build Coastguard Worker GLuint texTarget; 428*8975f5c5SAndroid Build Coastguard Worker GLubyte data[4] = {7, 51, 197, 231}; 429*8975f5c5SAndroid Build Coastguard Worker sourceMetalTarget2D_helper(data, kDefaultAttribs, &image, &texTarget); 430*8975f5c5SAndroid Build Coastguard Worker 431*8975f5c5SAndroid Build Coastguard Worker // Use texture target bound to egl image as source and render to framebuffer 432*8975f5c5SAndroid Build Coastguard Worker // Verify that data in framebuffer matches that in the egl image 433*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(texTarget, data); 434*8975f5c5SAndroid Build Coastguard Worker 435*8975f5c5SAndroid Build Coastguard Worker // Clean up 436*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(window->getDisplay(), image); 437*8975f5c5SAndroid Build Coastguard Worker glDeleteTextures(1, &texTarget); 438*8975f5c5SAndroid Build Coastguard Worker} 439*8975f5c5SAndroid Build Coastguard Worker 440*8975f5c5SAndroid Build Coastguard Worker// Create source metal EGL image, target 2D texture, then trigger texture respecification. 441*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, SourceMetal2DTargetTextureRespecifySize) 442*8975f5c5SAndroid Build Coastguard Worker{ 443*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 444*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 445*8975f5c5SAndroid Build Coastguard Worker 446*8975f5c5SAndroid Build Coastguard Worker EGLWindow *window = getEGLWindow(); 447*8975f5c5SAndroid Build Coastguard Worker 448*8975f5c5SAndroid Build Coastguard Worker // Create the Image 449*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image; 450*8975f5c5SAndroid Build Coastguard Worker GLuint texTarget; 451*8975f5c5SAndroid Build Coastguard Worker GLubyte data[4] = {7, 51, 197, 231}; 452*8975f5c5SAndroid Build Coastguard Worker sourceMetalTarget2D_helper(data, kDefaultAttribs, &image, &texTarget); 453*8975f5c5SAndroid Build Coastguard Worker 454*8975f5c5SAndroid Build Coastguard Worker // Use texture target bound to egl image as source and render to framebuffer 455*8975f5c5SAndroid Build Coastguard Worker // Verify that data in framebuffer matches that in the egl image 456*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(texTarget, data); 457*8975f5c5SAndroid Build Coastguard Worker 458*8975f5c5SAndroid Build Coastguard Worker // Respecify texture size and verify results 459*8975f5c5SAndroid Build Coastguard Worker std::array<GLubyte, 16> referenceColor; 460*8975f5c5SAndroid Build Coastguard Worker referenceColor.fill(127); 461*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texTarget); 462*8975f5c5SAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 463*8975f5c5SAndroid Build Coastguard Worker referenceColor.data()); 464*8975f5c5SAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 465*8975f5c5SAndroid Build Coastguard Worker referenceColor.data()); 466*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR(); 467*8975f5c5SAndroid Build Coastguard Worker 468*8975f5c5SAndroid Build Coastguard Worker // Expect that the target texture has the reference color values 469*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(texTarget, referenceColor.data()); 470*8975f5c5SAndroid Build Coastguard Worker 471*8975f5c5SAndroid Build Coastguard Worker // Clean up 472*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(window->getDisplay(), image); 473*8975f5c5SAndroid Build Coastguard Worker glDeleteTextures(1, &texTarget); 474*8975f5c5SAndroid Build Coastguard Worker} 475*8975f5c5SAndroid Build Coastguard Worker 476*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL can sample from a texture bound with Metal texture slice. 477*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, SourceMetalTarget2DArray) 478*8975f5c5SAndroid Build Coastguard Worker{ 479*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 480*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 481*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = createMtlTexture2DArray(1, 1, 3, MTLPixelFormatRGBA8Unorm); 482*8975f5c5SAndroid Build Coastguard Worker 483*8975f5c5SAndroid Build Coastguard Worker GLubyte data0[4] = {93, 83, 75, 128}; 484*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 485*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 486*8975f5c5SAndroid Build Coastguard Worker slice:0 487*8975f5c5SAndroid Build Coastguard Worker withBytes:data0 488*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 489*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 490*8975f5c5SAndroid Build Coastguard Worker GLubyte data1[4] = {7, 51, 197, 231}; 491*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 492*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 493*8975f5c5SAndroid Build Coastguard Worker slice:1 494*8975f5c5SAndroid Build Coastguard Worker withBytes:data1 495*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 496*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 497*8975f5c5SAndroid Build Coastguard Worker GLubyte data2[4] = {33, 51, 44, 33}; 498*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 499*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 500*8975f5c5SAndroid Build Coastguard Worker slice:2 501*8975f5c5SAndroid Build Coastguard Worker withBytes:data2 502*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 503*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 504*8975f5c5SAndroid Build Coastguard Worker 505*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 506*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image0 = 507*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 508*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), nullptr); 509*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 510*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs1[] = {EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, 1, EGL_NONE}; 511*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image1 = 512*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 513*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs1); 514*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 515*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs2[] = {EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, 2, EGL_NONE}; 516*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image2 = 517*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 518*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs2); 519*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 520*8975f5c5SAndroid Build Coastguard Worker 521*8975f5c5SAndroid Build Coastguard Worker GLTexture targetTexture; 522*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, targetTexture); 523*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image0); 524*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(targetTexture, data0); 525*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image1); 526*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(targetTexture, data1); 527*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image2); 528*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(targetTexture, data2); 529*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image0); 530*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image1); 531*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image2); 532*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 533*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 534*8975f5c5SAndroid Build Coastguard Worker} 535*8975f5c5SAndroid Build Coastguard Worker 536*8975f5c5SAndroid Build Coastguard Worker// Test that bound slice to EGLImage is not affected by releasing the source texture. 537*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, SourceMetalTarget2DArrayReleasedSourceOk) 538*8975f5c5SAndroid Build Coastguard Worker{ 539*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 540*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 541*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = createMtlTexture2DArray(1, 1, 3, MTLPixelFormatRGBA8Unorm); 542*8975f5c5SAndroid Build Coastguard Worker 543*8975f5c5SAndroid Build Coastguard Worker GLubyte data1[4] = {7, 51, 197, 231}; 544*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 545*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 546*8975f5c5SAndroid Build Coastguard Worker slice:1 547*8975f5c5SAndroid Build Coastguard Worker withBytes:data1 548*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 549*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 550*8975f5c5SAndroid Build Coastguard Worker 551*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 552*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs1[] = {EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, 1, EGL_NONE}; 553*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image1 = 554*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 555*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs1); 556*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 557*8975f5c5SAndroid Build Coastguard Worker // This is being tested: release the source texture but the slice keeps working. 558*8975f5c5SAndroid Build Coastguard Worker textureMtl = {}; 559*8975f5c5SAndroid Build Coastguard Worker GLTexture targetTexture; 560*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, targetTexture); 561*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image1); 562*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(targetTexture, data1); 563*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image1); 564*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 565*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 566*8975f5c5SAndroid Build Coastguard Worker} 567*8975f5c5SAndroid Build Coastguard Worker 568*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL can draw to a texture bound with Metal texture. 569*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, DrawMetalTarget2D) 570*8975f5c5SAndroid Build Coastguard Worker{ 571*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 572*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 573*8975f5c5SAndroid Build Coastguard Worker 574*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 575*8975f5c5SAndroid Build Coastguard Worker 576*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = createMtlTexture2D(1, 1, MTLPixelFormatRGBA8Unorm); 577*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 578*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 579*8975f5c5SAndroid Build Coastguard Worker slice:0 580*8975f5c5SAndroid Build Coastguard Worker withBytes:GLColor::red.data() 581*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 582*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 583*8975f5c5SAndroid Build Coastguard Worker 584*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 585*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 586*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), nullptr); 587*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 588*8975f5c5SAndroid Build Coastguard Worker 589*8975f5c5SAndroid Build Coastguard Worker GLTexture texture; 590*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture); 591*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 592*8975f5c5SAndroid Build Coastguard Worker 593*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer targetFbo; 594*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, targetFbo); 595*8975f5c5SAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 596*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 597*8975f5c5SAndroid Build Coastguard Worker 598*8975f5c5SAndroid Build Coastguard Worker glViewport(0, 0, 1, 1); 599*8975f5c5SAndroid Build Coastguard Worker drawColorQuad(GLColor::magenta); 600*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 601*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image); 602*8975f5c5SAndroid Build Coastguard Worker eglWaitUntilWorkScheduledANGLE(display); 603*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 604*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 605*8975f5c5SAndroid Build Coastguard Worker 606*8975f5c5SAndroid Build Coastguard Worker GLColor result; 607*8975f5c5SAndroid Build Coastguard Worker getTextureSliceBytes(textureMtl, 4, MTLRegionMake2D(0, 0, 1, 1), 0, 0, {result.data(), 4}); 608*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(result, GLColor::magenta); 609*8975f5c5SAndroid Build Coastguard Worker} 610*8975f5c5SAndroid Build Coastguard Worker 611*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL can draw to a texture bound with Metal texture slice. 612*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, DrawMetalTarget2DArray) 613*8975f5c5SAndroid Build Coastguard Worker{ 614*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 615*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 616*8975f5c5SAndroid Build Coastguard Worker 617*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 618*8975f5c5SAndroid Build Coastguard Worker 619*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = createMtlTexture2DArray(1, 1, 2, MTLPixelFormatRGBA8Unorm); 620*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 621*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 622*8975f5c5SAndroid Build Coastguard Worker slice:0 623*8975f5c5SAndroid Build Coastguard Worker withBytes:GLColor::red.data() 624*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 625*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 626*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 627*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 628*8975f5c5SAndroid Build Coastguard Worker slice:1 629*8975f5c5SAndroid Build Coastguard Worker withBytes:GLColor::red.data() 630*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 631*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 632*8975f5c5SAndroid Build Coastguard Worker 633*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, 1, EGL_NONE}; 634*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 635*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 636*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 637*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 638*8975f5c5SAndroid Build Coastguard Worker 639*8975f5c5SAndroid Build Coastguard Worker GLTexture texture; 640*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture); 641*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 642*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 643*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer targetFbo; 644*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, targetFbo); 645*8975f5c5SAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 646*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 647*8975f5c5SAndroid Build Coastguard Worker 648*8975f5c5SAndroid Build Coastguard Worker glViewport(0, 0, 1, 1); 649*8975f5c5SAndroid Build Coastguard Worker drawColorQuad(GLColor::magenta); 650*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 651*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image); 652*8975f5c5SAndroid Build Coastguard Worker eglWaitUntilWorkScheduledANGLE(display); 653*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 654*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 655*8975f5c5SAndroid Build Coastguard Worker 656*8975f5c5SAndroid Build Coastguard Worker GLColor result; 657*8975f5c5SAndroid Build Coastguard Worker getTextureSliceBytes(textureMtl, 4, MTLRegionMake2D(0, 0, 1, 1), 0, 1, {result.data(), 4}); 658*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(result, GLColor::magenta); 659*8975f5c5SAndroid Build Coastguard Worker} 660*8975f5c5SAndroid Build Coastguard Worker 661*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL can blit to a texture bound with Metal texture slice. 662*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, BlitMetalTarget2DArray) 663*8975f5c5SAndroid Build Coastguard Worker{ 664*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 665*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 666*8975f5c5SAndroid Build Coastguard Worker 667*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 668*8975f5c5SAndroid Build Coastguard Worker 669*8975f5c5SAndroid Build Coastguard Worker GLTexture colorBuffer; 670*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, colorBuffer); 671*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 672*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 673*8975f5c5SAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); 674*8975f5c5SAndroid Build Coastguard Worker glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, GLColor::green.data()); 675*8975f5c5SAndroid Build Coastguard Worker glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 676*8975f5c5SAndroid Build Coastguard Worker GLColor::yellow.data()); 677*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 678*8975f5c5SAndroid Build Coastguard Worker 679*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer sourceFbo; 680*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, sourceFbo); 681*8975f5c5SAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorBuffer, 0); 682*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 683*8975f5c5SAndroid Build Coastguard Worker 684*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = createMtlTexture2DArray(1, 1, 2, MTLPixelFormatRGBA8Unorm); 685*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 686*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 687*8975f5c5SAndroid Build Coastguard Worker slice:0 688*8975f5c5SAndroid Build Coastguard Worker withBytes:GLColor::red.data() 689*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 690*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 691*8975f5c5SAndroid Build Coastguard Worker [textureMtl replaceRegion:MTLRegionMake2D(0, 0, 1, 1) 692*8975f5c5SAndroid Build Coastguard Worker mipmapLevel:0 693*8975f5c5SAndroid Build Coastguard Worker slice:1 694*8975f5c5SAndroid Build Coastguard Worker withBytes:GLColor::red.data() 695*8975f5c5SAndroid Build Coastguard Worker bytesPerRow:4 696*8975f5c5SAndroid Build Coastguard Worker bytesPerImage:4]; 697*8975f5c5SAndroid Build Coastguard Worker 698*8975f5c5SAndroid Build Coastguard Worker for (int slice = 0; slice < 2; ++slice) 699*8975f5c5SAndroid Build Coastguard Worker { 700*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_METAL_TEXTURE_ARRAY_SLICE_ANGLE, slice, EGL_NONE}; 701*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 702*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 703*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 704*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 705*8975f5c5SAndroid Build Coastguard Worker 706*8975f5c5SAndroid Build Coastguard Worker GLTexture texture; 707*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture); 708*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 709*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, 0); 710*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(texture, GLColor::red.data()); 711*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 712*8975f5c5SAndroid Build Coastguard Worker 713*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer targetFbo; 714*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, targetFbo); 715*8975f5c5SAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 716*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 717*8975f5c5SAndroid Build Coastguard Worker 718*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, sourceFbo); 719*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, targetFbo); 720*8975f5c5SAndroid Build Coastguard Worker glBlitFramebufferANGLE(slice, 0, slice + 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); 721*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 722*8975f5c5SAndroid Build Coastguard Worker 723*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, 0); 724*8975f5c5SAndroid Build Coastguard Worker verifyResults2D(texture, slice == 0 ? GLColor::green.data() : GLColor::yellow.data()); 725*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image); 726*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 727*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 728*8975f5c5SAndroid Build Coastguard Worker } 729*8975f5c5SAndroid Build Coastguard Worker eglWaitUntilWorkScheduledANGLE(display); 730*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 731*8975f5c5SAndroid Build Coastguard Worker 732*8975f5c5SAndroid Build Coastguard Worker GLColor result; 733*8975f5c5SAndroid Build Coastguard Worker getTextureSliceBytes(textureMtl, 4, MTLRegionMake2D(0, 0, 1, 1), 0, 0, {result.data(), 4}); 734*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(result, GLColor::green); 735*8975f5c5SAndroid Build Coastguard Worker getTextureSliceBytes(textureMtl, 4, MTLRegionMake2D(0, 0, 1, 1), 0, 1, {result.data(), 4}); 736*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(result, GLColor::yellow); 737*8975f5c5SAndroid Build Coastguard Worker} 738*8975f5c5SAndroid Build Coastguard Worker 739*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL can override the internal format for a texture bound with 740*8975f5c5SAndroid Build Coastguard Worker// Metal texture. 741*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, OverrideMetalTextureInternalFormat) 742*8975f5c5SAndroid Build Coastguard Worker{ 743*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 744*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 745*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(hasDepth24Stencil8PixelFormat()); 746*8975f5c5SAndroid Build Coastguard Worker 747*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 748*8975f5c5SAndroid Build Coastguard Worker 749*8975f5c5SAndroid Build Coastguard Worker // On iOS devices, GL_DEPTH24_STENCIL8 is unavailable and is interally converted into 750*8975f5c5SAndroid Build Coastguard Worker // GL_DEPTH32F_STENCIL8. This tests the ability to attach MTLPixelFormatDepth32Float_Stencil8 751*8975f5c5SAndroid Build Coastguard Worker // and have GL treat it as GL_DEPTH24_STENCIL8 instead of GL_DEPTH32F_STENCIL8. 752*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = 753*8975f5c5SAndroid Build Coastguard Worker createMtlTexture2DArray(1, 1, 1, MTLPixelFormatDepth32Float_Stencil8); 754*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_DEPTH24_STENCIL8, EGL_NONE}; 755*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 756*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 757*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 758*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 759*8975f5c5SAndroid Build Coastguard Worker EXPECT_NE(image, nullptr); 760*8975f5c5SAndroid Build Coastguard Worker} 761*8975f5c5SAndroid Build Coastguard Worker 762*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL can override the internal format for a texture bound with 763*8975f5c5SAndroid Build Coastguard Worker// Metal texture and that rendering to the texture is successful. 764*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, RenderingTest) 765*8975f5c5SAndroid Build Coastguard Worker{ 766*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 767*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 768*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(hasDepth24Stencil8PixelFormat()); 769*8975f5c5SAndroid Build Coastguard Worker 770*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 771*8975f5c5SAndroid Build Coastguard Worker 772*8975f5c5SAndroid Build Coastguard Worker const int bufferSize = 32; 773*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = 774*8975f5c5SAndroid Build Coastguard Worker createMtlTexture2DArray(bufferSize, bufferSize, 1, MTLPixelFormatDepth32Float_Stencil8); 775*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_DEPTH24_STENCIL8, EGL_NONE}; 776*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 777*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 778*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 779*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 780*8975f5c5SAndroid Build Coastguard Worker EXPECT_NE(image, nullptr); 781*8975f5c5SAndroid Build Coastguard Worker 782*8975f5c5SAndroid Build Coastguard Worker GLRenderbuffer colorBuffer; 783*8975f5c5SAndroid Build Coastguard Worker glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer); 784*8975f5c5SAndroid Build Coastguard Worker glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, bufferSize, bufferSize); 785*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 786*8975f5c5SAndroid Build Coastguard Worker 787*8975f5c5SAndroid Build Coastguard Worker GLRenderbuffer depthStencilBuffer; 788*8975f5c5SAndroid Build Coastguard Worker glBindRenderbuffer(GL_RENDERBUFFER, depthStencilBuffer); 789*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image); 790*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 791*8975f5c5SAndroid Build Coastguard Worker 792*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer fb; 793*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, fb); 794*8975f5c5SAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBuffer); 795*8975f5c5SAndroid Build Coastguard Worker if (getClientMajorVersion() >= 3) 796*8975f5c5SAndroid Build Coastguard Worker { 797*8975f5c5SAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 798*8975f5c5SAndroid Build Coastguard Worker depthStencilBuffer); 799*8975f5c5SAndroid Build Coastguard Worker } 800*8975f5c5SAndroid Build Coastguard Worker else 801*8975f5c5SAndroid Build Coastguard Worker { 802*8975f5c5SAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 803*8975f5c5SAndroid Build Coastguard Worker depthStencilBuffer); 804*8975f5c5SAndroid Build Coastguard Worker glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 805*8975f5c5SAndroid Build Coastguard Worker depthStencilBuffer); 806*8975f5c5SAndroid Build Coastguard Worker } 807*8975f5c5SAndroid Build Coastguard Worker 808*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 809*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER); 810*8975f5c5SAndroid Build Coastguard Worker 811*8975f5c5SAndroid Build Coastguard Worker glClearColor(1.f, 0.f, 0.f, 1.f); 812*8975f5c5SAndroid Build Coastguard Worker glClearDepthf(1.f); 813*8975f5c5SAndroid Build Coastguard Worker glClearStencil(0x55); 814*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 815*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 816*8975f5c5SAndroid Build Coastguard Worker 817*8975f5c5SAndroid Build Coastguard Worker glEnable(GL_DEPTH_TEST); 818*8975f5c5SAndroid Build Coastguard Worker glDepthFunc(GL_LESS); 819*8975f5c5SAndroid Build Coastguard Worker 820*8975f5c5SAndroid Build Coastguard Worker glEnable(GL_STENCIL_TEST); 821*8975f5c5SAndroid Build Coastguard Worker glStencilFunc(GL_EQUAL, 0x55, 0xFF); 822*8975f5c5SAndroid Build Coastguard Worker glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 823*8975f5c5SAndroid Build Coastguard Worker glStencilMask(0xFF); 824*8975f5c5SAndroid Build Coastguard Worker 825*8975f5c5SAndroid Build Coastguard Worker // Draw green. 826*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green()); 827*8975f5c5SAndroid Build Coastguard Worker drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.95f); 828*8975f5c5SAndroid Build Coastguard Worker 829*8975f5c5SAndroid Build Coastguard Worker // Verify that green was drawn. 830*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green); 831*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(0, bufferSize - 1, GLColor::green); 832*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(bufferSize - 1, 0, GLColor::green); 833*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_COLOR_EQ(bufferSize - 1, bufferSize - 1, GLColor::green); 834*8975f5c5SAndroid Build Coastguard Worker 835*8975f5c5SAndroid Build Coastguard Worker eglDestroyImageKHR(display, image); 836*8975f5c5SAndroid Build Coastguard Worker} 837*8975f5c5SAndroid Build Coastguard Worker 838*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL override the with a bad internal format for a texture bound 839*8975f5c5SAndroid Build Coastguard Worker// with Metal texture fails. 840*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, OverrideMetalTextureInternalFormatBadFormat) 841*8975f5c5SAndroid Build Coastguard Worker{ 842*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 843*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 844*8975f5c5SAndroid Build Coastguard Worker 845*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 846*8975f5c5SAndroid Build Coastguard Worker 847*8975f5c5SAndroid Build Coastguard Worker // On iOS devices, GL_DEPTH24_STENCIL8 is unavailable and is interally converted into 848*8975f5c5SAndroid Build Coastguard Worker // GL_DEPTH32F_STENCIL8. This tests the ability to attach MTLPixelFormatDepth32Float_Stencil8 849*8975f5c5SAndroid Build Coastguard Worker // and have GL treat it as GL_DEPTH24_STENCIL8 instead of GL_DEPTH32F_STENCIL8. 850*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = 851*8975f5c5SAndroid Build Coastguard Worker createMtlTexture2DArray(1, 1, 1, MTLPixelFormatDepth32Float_Stencil8); 852*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_TRIANGLES, EGL_NONE}; 853*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 854*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 855*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 856*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE); 857*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(image, nullptr); 858*8975f5c5SAndroid Build Coastguard Worker} 859*8975f5c5SAndroid Build Coastguard Worker 860*8975f5c5SAndroid Build Coastguard Worker// Tests that OpenGL override the with an incompatible internal format for a texture bound 861*8975f5c5SAndroid Build Coastguard Worker// with Metal texture fails. 862*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, OverrideMetalTextureInternalFormatIncompatibleFormat) 863*8975f5c5SAndroid Build Coastguard Worker{ 864*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 865*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 866*8975f5c5SAndroid Build Coastguard Worker 867*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = getEGLWindow()->getDisplay(); 868*8975f5c5SAndroid Build Coastguard Worker 869*8975f5c5SAndroid Build Coastguard Worker // On iOS devices, GL_DEPTH24_STENCIL8 is unavailable and is interally converted into 870*8975f5c5SAndroid Build Coastguard Worker // GL_DEPTH32F_STENCIL8. This tests the ability to attach MTLPixelFormatDepth32Float_Stencil8 871*8975f5c5SAndroid Build Coastguard Worker // and have GL treat it as GL_DEPTH24_STENCIL8 instead of GL_DEPTH32F_STENCIL8. 872*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = 873*8975f5c5SAndroid Build Coastguard Worker createMtlTexture2DArray(1, 1, 1, MTLPixelFormatDepth32Float_Stencil8); 874*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA8, EGL_NONE}; 875*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 876*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 877*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 878*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_ERROR(EGL_BAD_ATTRIBUTE); 879*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(image, nullptr); 880*8975f5c5SAndroid Build Coastguard Worker} 881*8975f5c5SAndroid Build Coastguard Worker 882*8975f5c5SAndroid Build Coastguard Worker// Test this scenario: 883*8975f5c5SAndroid Build Coastguard Worker// Metal and GL share the same MTL texture (called texture1). 884*8975f5c5SAndroid Build Coastguard Worker// GL Context draws to texture1: 885*8975f5c5SAndroid Build Coastguard Worker// - draw. 886*8975f5c5SAndroid Build Coastguard Worker// - upload texture2 887*8975f5c5SAndroid Build Coastguard Worker// - draw using the texture2 as source. 888*8975f5c5SAndroid Build Coastguard Worker// - place a sync object. 889*8975f5c5SAndroid Build Coastguard Worker// 890*8975f5c5SAndroid Build Coastguard Worker// Metal reads the texture1: 891*8975f5c5SAndroid Build Coastguard Worker// - wait for the shared event sync object. 892*8975f5c5SAndroid Build Coastguard Worker// - copy the texture1 to a buffer. 893*8975f5c5SAndroid Build Coastguard Worker// - The buffer should contain color from texture2 after being uploaded. 894*8975f5c5SAndroid Build Coastguard Worker// 895*8975f5c5SAndroid Build Coastguard Worker// Previously this would cause a bug in Metal backend because texture upload would 896*8975f5c5SAndroid Build Coastguard Worker// create a new blit encoder in a middle of a render pass and the command buffer would mistrack the 897*8975f5c5SAndroid Build Coastguard Worker// ongoing render encoder. Thus making the metal sync object being placed incorrectly. 898*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageTestMetal, SharedEventSyncWhenThereIsTextureUploadBetweenDraws) 899*8975f5c5SAndroid Build Coastguard Worker{ 900*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 901*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 902*8975f5c5SAndroid Build Coastguard Worker 903*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display1 = getEGLWindow()->getDisplay(); 904*8975f5c5SAndroid Build Coastguard Worker 905*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3); 906*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF( 907*8975f5c5SAndroid Build Coastguard Worker !IsEGLDisplayExtensionEnabled(display1, "EGL_ANGLE_metal_shared_event_sync")); 908*8975f5c5SAndroid Build Coastguard Worker 909*8975f5c5SAndroid Build Coastguard Worker @autoreleasepool 910*8975f5c5SAndroid Build Coastguard Worker { 911*8975f5c5SAndroid Build Coastguard Worker // Create MTLTexture 912*8975f5c5SAndroid Build Coastguard Worker constexpr int kSharedTextureSize = 1024; 913*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = 914*8975f5c5SAndroid Build Coastguard Worker createMtlTexture2D(kSharedTextureSize, kSharedTextureSize, MTLPixelFormatR32Sint); 915*8975f5c5SAndroid Build Coastguard Worker 916*8975f5c5SAndroid Build Coastguard Worker // Create SharedEvent 917*8975f5c5SAndroid Build Coastguard Worker id<MTLDevice> deviceMtl = getMtlDevice(); 918*8975f5c5SAndroid Build Coastguard Worker id<MTLSharedEvent> sharedEventMtl = CreateMetalSharedEvent(deviceMtl); 919*8975f5c5SAndroid Build Coastguard Worker 920*8975f5c5SAndroid Build Coastguard Worker // -------------------------- Metal --------------------------- 921*8975f5c5SAndroid Build Coastguard Worker // Create a buffer on Metal to store the final value. 922*8975f5c5SAndroid Build Coastguard Worker ScopedMetalBufferRef dstBuffer( 923*8975f5c5SAndroid Build Coastguard Worker [deviceMtl newBufferWithLength:sizeof(float) options:MTLResourceStorageModeShared]); 924*8975f5c5SAndroid Build Coastguard Worker ScopedMetalCommandQueueRef commandQueue([deviceMtl newCommandQueue]); 925*8975f5c5SAndroid Build Coastguard Worker id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer]; 926*8975f5c5SAndroid Build Coastguard Worker 927*8975f5c5SAndroid Build Coastguard Worker // Wait for drawing on GL context to finish on server side. 928*8975f5c5SAndroid Build Coastguard Worker // Note: we issue a wait even before the draw calls are issued on GL context. 929*8975f5c5SAndroid Build Coastguard Worker // GL context will issue a signaling later (see below). 930*8975f5c5SAndroid Build Coastguard Worker constexpr uint64_t kSignalValue = 0xff; 931*8975f5c5SAndroid Build Coastguard Worker [commandBuffer encodeWaitForEvent:sharedEventMtl value:kSignalValue]; 932*8975f5c5SAndroid Build Coastguard Worker 933*8975f5c5SAndroid Build Coastguard Worker // Copy a pixel from texture1 to dstBuffer 934*8975f5c5SAndroid Build Coastguard Worker id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder]; 935*8975f5c5SAndroid Build Coastguard Worker [blitEncoder copyFromTexture:textureMtl 936*8975f5c5SAndroid Build Coastguard Worker sourceSlice:0 937*8975f5c5SAndroid Build Coastguard Worker sourceLevel:0 938*8975f5c5SAndroid Build Coastguard Worker sourceOrigin:MTLOriginMake(kSharedTextureSize - 1, kSharedTextureSize - 2, 939*8975f5c5SAndroid Build Coastguard Worker 0) 940*8975f5c5SAndroid Build Coastguard Worker sourceSize:MTLSizeMake(1, 1, 1) 941*8975f5c5SAndroid Build Coastguard Worker toBuffer:dstBuffer 942*8975f5c5SAndroid Build Coastguard Worker destinationOffset:0 943*8975f5c5SAndroid Build Coastguard Worker destinationBytesPerRow:sizeof(float) * kSharedTextureSize 944*8975f5c5SAndroid Build Coastguard Worker destinationBytesPerImage:0]; 945*8975f5c5SAndroid Build Coastguard Worker [blitEncoder endEncoding]; 946*8975f5c5SAndroid Build Coastguard Worker [commandBuffer commit]; 947*8975f5c5SAndroid Build Coastguard Worker 948*8975f5c5SAndroid Build Coastguard Worker // -------------------------- GL context --------------------------- 949*8975f5c5SAndroid Build Coastguard Worker constexpr int kNumValues = 1000; 950*8975f5c5SAndroid Build Coastguard Worker // A deliberately slow shader that reads a texture many times then write 951*8975f5c5SAndroid Build Coastguard Worker // the sum value to an ouput varible. 952*8975f5c5SAndroid Build Coastguard Worker constexpr char kFS[] = R"(#version 300 es 953*8975f5c5SAndroid Build Coastguard Workerout highp ivec4 outColor; 954*8975f5c5SAndroid Build Coastguard Worker 955*8975f5c5SAndroid Build Coastguard Workeruniform highp isampler2D u_valuesTex; 956*8975f5c5SAndroid Build Coastguard Worker 957*8975f5c5SAndroid Build Coastguard Workervoid main() 958*8975f5c5SAndroid Build Coastguard Worker{ 959*8975f5c5SAndroid Build Coastguard Worker highp int value = 0; 960*8975f5c5SAndroid Build Coastguard Worker for (int i = 0; i < 1000; ++i) { 961*8975f5c5SAndroid Build Coastguard Worker highp float uCoords = (float(i) + 0.5) / float(1000); 962*8975f5c5SAndroid Build Coastguard Worker value += textureLod(u_valuesTex, vec2(uCoords, 0.0), 0.0).r; 963*8975f5c5SAndroid Build Coastguard Worker } 964*8975f5c5SAndroid Build Coastguard Worker 965*8975f5c5SAndroid Build Coastguard Worker outColor = ivec4(value); 966*8975f5c5SAndroid Build Coastguard Worker})"; 967*8975f5c5SAndroid Build Coastguard Worker 968*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(complexProgram, essl3_shaders::vs::Simple(), kFS); 969*8975f5c5SAndroid Build Coastguard Worker GLint valuesTexLocation = glGetUniformLocation(complexProgram, "u_valuesTex"); 970*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(valuesTexLocation, -1); 971*8975f5c5SAndroid Build Coastguard Worker 972*8975f5c5SAndroid Build Coastguard Worker // Create the shared texture from MTLTexture. 973*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 974*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display1, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 975*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), kDefaultAttribs); 976*8975f5c5SAndroid Build Coastguard Worker EXPECT_EGL_SUCCESS(); 977*8975f5c5SAndroid Build Coastguard Worker GLTexture texture1; 978*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture1); 979*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 980*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_ERROR(GL_NO_ERROR); 981*8975f5c5SAndroid Build Coastguard Worker glViewport(0, 0, kSharedTextureSize, kSharedTextureSize); 982*8975f5c5SAndroid Build Coastguard Worker 983*8975f5c5SAndroid Build Coastguard Worker // Create texture holding multiple values to be accumulated in shader. 984*8975f5c5SAndroid Build Coastguard Worker GLTexture texture2; 985*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture2); 986*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 987*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 988*8975f5c5SAndroid Build Coastguard Worker glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, kNumValues, 1, 0, GL_RED_INTEGER, GL_INT, nullptr); 989*8975f5c5SAndroid Build Coastguard Worker glFlush(); 990*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_ERROR(GL_NO_ERROR); 991*8975f5c5SAndroid Build Coastguard Worker 992*8975f5c5SAndroid Build Coastguard Worker // Using GL context to draw to the texture1 993*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture1); 994*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer framebuffer1; 995*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, framebuffer1); 996*8975f5c5SAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture1, 0); 997*8975f5c5SAndroid Build Coastguard Worker 998*8975f5c5SAndroid Build Coastguard Worker // First draw with initial color 999*8975f5c5SAndroid Build Coastguard Worker { 1000*8975f5c5SAndroid Build Coastguard Worker constexpr char kSimpleFS[] = R"(#version 300 es 1001*8975f5c5SAndroid Build Coastguard Workerout highp ivec4 outColor; 1002*8975f5c5SAndroid Build Coastguard Worker 1003*8975f5c5SAndroid Build Coastguard Workervoid main() 1004*8975f5c5SAndroid Build Coastguard Worker{ 1005*8975f5c5SAndroid Build Coastguard Worker outColor = ivec4(1); 1006*8975f5c5SAndroid Build Coastguard Worker})"; 1007*8975f5c5SAndroid Build Coastguard Worker ANGLE_GL_PROGRAM(colorProgram, angle::essl3_shaders::vs::Simple(), kSimpleFS); 1008*8975f5c5SAndroid Build Coastguard Worker drawQuad(colorProgram, angle::essl3_shaders::PositionAttrib(), 0.5f); 1009*8975f5c5SAndroid Build Coastguard Worker } 1010*8975f5c5SAndroid Build Coastguard Worker 1011*8975f5c5SAndroid Build Coastguard Worker // Upload the texture2 1012*8975f5c5SAndroid Build Coastguard Worker std::vector<int32_t> values(kNumValues); 1013*8975f5c5SAndroid Build Coastguard Worker for (size_t i = 0; i < values.size(); ++i) 1014*8975f5c5SAndroid Build Coastguard Worker { 1015*8975f5c5SAndroid Build Coastguard Worker values[i] = i; 1016*8975f5c5SAndroid Build Coastguard Worker } 1017*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture2); 1018*8975f5c5SAndroid Build Coastguard Worker glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kNumValues, 1, GL_RED_INTEGER, GL_INT, 1019*8975f5c5SAndroid Build Coastguard Worker values.data()); 1020*8975f5c5SAndroid Build Coastguard Worker 1021*8975f5c5SAndroid Build Coastguard Worker // 2nd draw call draw the texture2 to texture1. 1022*8975f5c5SAndroid Build Coastguard Worker glUseProgram(complexProgram); 1023*8975f5c5SAndroid Build Coastguard Worker drawQuad(complexProgram, angle::essl1_shaders::PositionAttrib(), 0.5f); 1024*8975f5c5SAndroid Build Coastguard Worker 1025*8975f5c5SAndroid Build Coastguard Worker // Place a sync object on GL context's commands stream. 1026*8975f5c5SAndroid Build Coastguard Worker EGLSync syncGL = CreateEGLSyncFromMetalSharedEvent(display1, sharedEventMtl, kSignalValue, 1027*8975f5c5SAndroid Build Coastguard Worker /*signaled=*/false); 1028*8975f5c5SAndroid Build Coastguard Worker glFlush(); 1029*8975f5c5SAndroid Build Coastguard Worker 1030*8975f5c5SAndroid Build Coastguard Worker // -------------------------- Metal --------------------------- 1031*8975f5c5SAndroid Build Coastguard Worker [commandBuffer waitUntilCompleted]; 1032*8975f5c5SAndroid Build Coastguard Worker 1033*8975f5c5SAndroid Build Coastguard Worker // Read dstBuffer 1034*8975f5c5SAndroid Build Coastguard Worker const int32_t kExpectedSum = kNumValues * (kNumValues - 1) / 2; 1035*8975f5c5SAndroid Build Coastguard Worker int32_t *mappedInts = static_cast<int32_t *>(dstBuffer.get().contents); 1036*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(mappedInts[0], kExpectedSum); 1037*8975f5c5SAndroid Build Coastguard Worker 1038*8975f5c5SAndroid Build Coastguard Worker eglDestroySync(display1, syncGL); 1039*8975f5c5SAndroid Build Coastguard Worker eglDestroyImage(display1, image); 1040*8975f5c5SAndroid Build Coastguard Worker 1041*8975f5c5SAndroid Build Coastguard Worker } // @autoreleasepool 1042*8975f5c5SAndroid Build Coastguard Worker} 1043*8975f5c5SAndroid Build Coastguard Worker 1044*8975f5c5SAndroid Build Coastguard Workerclass ImageClearTestMetal : public ImageTestMetal 1045*8975f5c5SAndroid Build Coastguard Worker{ 1046*8975f5c5SAndroid Build Coastguard Worker protected: 1047*8975f5c5SAndroid Build Coastguard Worker ImageClearTestMetal() : ImageTestMetal() {} 1048*8975f5c5SAndroid Build Coastguard Worker 1049*8975f5c5SAndroid Build Coastguard Worker void RunUnsizedClearTest(MTLPixelFormat format) 1050*8975f5c5SAndroid Build Coastguard Worker { 1051*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt()); 1052*8975f5c5SAndroid Build Coastguard Worker ANGLE_SKIP_TEST_IF(!hasImageNativeMetalTextureExt()); 1053*8975f5c5SAndroid Build Coastguard Worker 1054*8975f5c5SAndroid Build Coastguard Worker EGLWindow *window = getEGLWindow(); 1055*8975f5c5SAndroid Build Coastguard Worker EGLDisplay display = window->getDisplay(); 1056*8975f5c5SAndroid Build Coastguard Worker 1057*8975f5c5SAndroid Build Coastguard Worker window->makeCurrent(); 1058*8975f5c5SAndroid Build Coastguard Worker 1059*8975f5c5SAndroid Build Coastguard Worker const GLint bufferSize = 32; 1060*8975f5c5SAndroid Build Coastguard Worker ScopedMetalTextureRef textureMtl = 1061*8975f5c5SAndroid Build Coastguard Worker createMtlTexture2DArray(bufferSize, bufferSize, 1, format); 1062*8975f5c5SAndroid Build Coastguard Worker EXPECT_TRUE(textureMtl); 1063*8975f5c5SAndroid Build Coastguard Worker 1064*8975f5c5SAndroid Build Coastguard Worker EGLint internalFormat = GL_NONE; 1065*8975f5c5SAndroid Build Coastguard Worker switch (format) 1066*8975f5c5SAndroid Build Coastguard Worker { 1067*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatR8Unorm: 1068*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatR16Unorm: 1069*8975f5c5SAndroid Build Coastguard Worker internalFormat = GL_RED_EXT; 1070*8975f5c5SAndroid Build Coastguard Worker break; 1071*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRG8Unorm: 1072*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRG16Unorm: 1073*8975f5c5SAndroid Build Coastguard Worker internalFormat = GL_RG_EXT; 1074*8975f5c5SAndroid Build Coastguard Worker break; 1075*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGBA8Unorm: 1076*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGBA16Float: 1077*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGB10A2Unorm: 1078*8975f5c5SAndroid Build Coastguard Worker internalFormat = GL_RGBA; 1079*8975f5c5SAndroid Build Coastguard Worker break; 1080*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGBA8Unorm_sRGB: 1081*8975f5c5SAndroid Build Coastguard Worker internalFormat = GL_SRGB_ALPHA_EXT; 1082*8975f5c5SAndroid Build Coastguard Worker break; 1083*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatBGRA8Unorm: 1084*8975f5c5SAndroid Build Coastguard Worker internalFormat = GL_BGRA_EXT; 1085*8975f5c5SAndroid Build Coastguard Worker break; 1086*8975f5c5SAndroid Build Coastguard Worker default: 1087*8975f5c5SAndroid Build Coastguard Worker break; 1088*8975f5c5SAndroid Build Coastguard Worker } 1089*8975f5c5SAndroid Build Coastguard Worker 1090*8975f5c5SAndroid Build Coastguard Worker const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, internalFormat, EGL_NONE}; 1091*8975f5c5SAndroid Build Coastguard Worker 1092*8975f5c5SAndroid Build Coastguard Worker EGLImageKHR image = 1093*8975f5c5SAndroid Build Coastguard Worker eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_METAL_TEXTURE_ANGLE, 1094*8975f5c5SAndroid Build Coastguard Worker reinterpret_cast<EGLClientBuffer>(textureMtl.get()), attribs); 1095*8975f5c5SAndroid Build Coastguard Worker ASSERT_EGL_SUCCESS(); 1096*8975f5c5SAndroid Build Coastguard Worker ASSERT_NE(image, EGL_NO_IMAGE_KHR); 1097*8975f5c5SAndroid Build Coastguard Worker 1098*8975f5c5SAndroid Build Coastguard Worker GLTexture texture; 1099*8975f5c5SAndroid Build Coastguard Worker glBindTexture(GL_TEXTURE_2D, texture); 1100*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1101*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1102*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1103*8975f5c5SAndroid Build Coastguard Worker glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1104*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 1105*8975f5c5SAndroid Build Coastguard Worker 1106*8975f5c5SAndroid Build Coastguard Worker glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); 1107*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 1108*8975f5c5SAndroid Build Coastguard Worker 1109*8975f5c5SAndroid Build Coastguard Worker GLFramebuffer fbo; 1110*8975f5c5SAndroid Build Coastguard Worker glBindFramebuffer(GL_FRAMEBUFFER, fbo); 1111*8975f5c5SAndroid Build Coastguard Worker glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 1112*8975f5c5SAndroid Build Coastguard Worker EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), 1113*8975f5c5SAndroid Build Coastguard Worker static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE)); 1114*8975f5c5SAndroid Build Coastguard Worker EXPECT_GL_NO_ERROR(); 1115*8975f5c5SAndroid Build Coastguard Worker 1116*8975f5c5SAndroid Build Coastguard Worker glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize)); 1117*8975f5c5SAndroid Build Coastguard Worker glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 1118*8975f5c5SAndroid Build Coastguard Worker glClear(GL_COLOR_BUFFER_BIT); 1119*8975f5c5SAndroid Build Coastguard Worker ASSERT_GL_NO_ERROR(); 1120*8975f5c5SAndroid Build Coastguard Worker 1121*8975f5c5SAndroid Build Coastguard Worker if (format == MTLPixelFormatRGBA16Float) 1122*8975f5c5SAndroid Build Coastguard Worker { 1123*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_32F_EQ(bufferSize / 2, bufferSize / 2, 1.0f, 1.0f, 1.0f, 1.0f); 1124*8975f5c5SAndroid Build Coastguard Worker } 1125*8975f5c5SAndroid Build Coastguard Worker else if (format == MTLPixelFormatR16Unorm) 1126*8975f5c5SAndroid Build Coastguard Worker { 1127*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_16_NEAR(bufferSize / 2, bufferSize / 2, 65535, 0, 0, 65535, 0); 1128*8975f5c5SAndroid Build Coastguard Worker } 1129*8975f5c5SAndroid Build Coastguard Worker else if (format == MTLPixelFormatRG16Unorm) 1130*8975f5c5SAndroid Build Coastguard Worker { 1131*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_16_NEAR(bufferSize / 2, bufferSize / 2, 65535, 65535, 0, 65535, 0); 1132*8975f5c5SAndroid Build Coastguard Worker } 1133*8975f5c5SAndroid Build Coastguard Worker else 1134*8975f5c5SAndroid Build Coastguard Worker { 1135*8975f5c5SAndroid Build Coastguard Worker GLuint readColor[4] = {0, 0, 0, 255}; 1136*8975f5c5SAndroid Build Coastguard Worker switch (format) 1137*8975f5c5SAndroid Build Coastguard Worker { 1138*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatR8Unorm: 1139*8975f5c5SAndroid Build Coastguard Worker readColor[0] = 255; 1140*8975f5c5SAndroid Build Coastguard Worker break; 1141*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRG8Unorm: 1142*8975f5c5SAndroid Build Coastguard Worker readColor[0] = readColor[1] = 255; 1143*8975f5c5SAndroid Build Coastguard Worker break; 1144*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGBA8Unorm: 1145*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGB10A2Unorm: 1146*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGBA16Float: 1147*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatRGBA8Unorm_sRGB: 1148*8975f5c5SAndroid Build Coastguard Worker case MTLPixelFormatBGRA8Unorm: 1149*8975f5c5SAndroid Build Coastguard Worker readColor[0] = readColor[1] = readColor[2] = 255; 1150*8975f5c5SAndroid Build Coastguard Worker break; 1151*8975f5c5SAndroid Build Coastguard Worker default: 1152*8975f5c5SAndroid Build Coastguard Worker break; 1153*8975f5c5SAndroid Build Coastguard Worker } 1154*8975f5c5SAndroid Build Coastguard Worker // Read back as GL_UNSIGNED_BYTE even though the texture might have more than 8bpc. 1155*8975f5c5SAndroid Build Coastguard Worker EXPECT_PIXEL_EQ(bufferSize / 2, bufferSize / 2, readColor[0], readColor[1], 1156*8975f5c5SAndroid Build Coastguard Worker readColor[2], readColor[3]); 1157*8975f5c5SAndroid Build Coastguard Worker } 1158*8975f5c5SAndroid Build Coastguard Worker } 1159*8975f5c5SAndroid Build Coastguard Worker}; 1160*8975f5c5SAndroid Build Coastguard Worker 1161*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedRGBA8) 1162*8975f5c5SAndroid Build Coastguard Worker{ 1163*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatRGBA8Unorm); 1164*8975f5c5SAndroid Build Coastguard Worker} 1165*8975f5c5SAndroid Build Coastguard Worker 1166*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedsRGBA8) 1167*8975f5c5SAndroid Build Coastguard Worker{ 1168*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatRGBA8Unorm_sRGB); 1169*8975f5c5SAndroid Build Coastguard Worker} 1170*8975f5c5SAndroid Build Coastguard Worker 1171*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedBGRA8) 1172*8975f5c5SAndroid Build Coastguard Worker{ 1173*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatBGRA8Unorm); 1174*8975f5c5SAndroid Build Coastguard Worker} 1175*8975f5c5SAndroid Build Coastguard Worker 1176*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedR8) 1177*8975f5c5SAndroid Build Coastguard Worker{ 1178*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatR8Unorm); 1179*8975f5c5SAndroid Build Coastguard Worker} 1180*8975f5c5SAndroid Build Coastguard Worker 1181*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedRG8) 1182*8975f5c5SAndroid Build Coastguard Worker{ 1183*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatRG8Unorm); 1184*8975f5c5SAndroid Build Coastguard Worker} 1185*8975f5c5SAndroid Build Coastguard Worker 1186*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedRGB10A2) 1187*8975f5c5SAndroid Build Coastguard Worker{ 1188*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatRGB10A2Unorm); 1189*8975f5c5SAndroid Build Coastguard Worker} 1190*8975f5c5SAndroid Build Coastguard Worker 1191*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedRGBAF16) 1192*8975f5c5SAndroid Build Coastguard Worker{ 1193*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatRGBA16Float); 1194*8975f5c5SAndroid Build Coastguard Worker} 1195*8975f5c5SAndroid Build Coastguard Worker 1196*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedR16) 1197*8975f5c5SAndroid Build Coastguard Worker{ 1198*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatR16Unorm); 1199*8975f5c5SAndroid Build Coastguard Worker} 1200*8975f5c5SAndroid Build Coastguard Worker 1201*8975f5c5SAndroid Build Coastguard WorkerTEST_P(ImageClearTestMetal, ClearUnsizedRG16) 1202*8975f5c5SAndroid Build Coastguard Worker{ 1203*8975f5c5SAndroid Build Coastguard Worker RunUnsizedClearTest(MTLPixelFormatRG16Unorm); 1204*8975f5c5SAndroid Build Coastguard Worker} 1205*8975f5c5SAndroid Build Coastguard Worker 1206*8975f5c5SAndroid Build Coastguard Worker// Use this to select which configurations (e.g. which renderer, which GLES major version) these 1207*8975f5c5SAndroid Build Coastguard Worker// tests should be run against. 1208*8975f5c5SAndroid Build Coastguard WorkerANGLE_INSTANTIATE_TEST(ImageTestMetal, ES2_METAL(), ES3_METAL()); 1209*8975f5c5SAndroid Build Coastguard WorkerANGLE_INSTANTIATE_TEST(ImageClearTestMetal, ES2_METAL(), ES3_METAL()); 1210*8975f5c5SAndroid Build Coastguard WorkerGTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageTestMetal); 1211*8975f5c5SAndroid Build Coastguard WorkerGTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageClearTestMetal); 1212*8975f5c5SAndroid Build Coastguard Worker} // namespace angle 1213