Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "Test.h"
      9 #if SK_SUPPORT_GPU
     10 #include "GrContext.h"
     11 #include "GrContextFactory.h"
     12 #include "gl/GrGLGpu.h"
     13 #include "gl/GrGLUtil.h"
     14 #include "gl/SkGLContext.h"
     15 
     16 static void cleanup(SkGLContext* glctx0, GrGLuint texID0, SkGLContext* glctx1, GrContext* grctx1,
     17                     const GrGLTextureInfo* grbackendtex1, GrEGLImage image1) {
     18     if (glctx1) {
     19         glctx1->makeCurrent();
     20         if (grctx1) {
     21             if (grbackendtex1) {
     22                 GrGLGpu* gpu1 = static_cast<GrGLGpu*>(grctx1->getGpu());
     23                 GrBackendObject handle = reinterpret_cast<GrBackendObject>(grbackendtex1);
     24                 gpu1->deleteTestingOnlyBackendTexture(handle, false);
     25             }
     26             grctx1->unref();
     27         }
     28         if (GR_EGL_NO_IMAGE != image1) {
     29             glctx1->destroyEGLImage(image1);
     30         }
     31     }
     32 
     33     glctx0->makeCurrent();
     34     if (texID0) {
     35         GR_GL_CALL(glctx0->gl(), DeleteTextures(1, &texID0));
     36     }
     37 }
     38 
     39 static void test_read_pixels(skiatest::Reporter* reporter, GrContext* context,
     40                              GrTexture* externalTexture, uint32_t expectedPixelValues[]) {
     41     int pixelCnt = externalTexture->width() * externalTexture->height();
     42     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
     43     memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
     44     bool read = externalTexture->readPixels(0, 0, externalTexture->width(),
     45                                             externalTexture->height(), kRGBA_8888_GrPixelConfig,
     46                                             pixels.get());
     47     if (!read) {
     48         ERRORF(reporter, "Error reading external texture.");
     49     }
     50     for (int i = 0; i < pixelCnt; ++i) {
     51         if (pixels.get()[i] != expectedPixelValues[i]) {
     52             ERRORF(reporter, "Error, external texture pixel value %d should be 0x%08x,"
     53                              " got 0x%08x.", i, expectedPixelValues[i], pixels.get()[i]);
     54             break;
     55         }
     56     }
     57 }
     58 
     59 static void test_write_pixels(skiatest::Reporter* reporter, GrContext* context,
     60                               GrTexture* externalTexture) {
     61     int pixelCnt = externalTexture->width() * externalTexture->height();
     62     SkAutoTMalloc<uint32_t> pixels(pixelCnt);
     63     memset(pixels.get(), 0, sizeof(uint32_t)*pixelCnt);
     64     bool write = externalTexture->writePixels(0, 0, 0, 0, kRGBA_8888_GrPixelConfig, pixels.get());
     65     REPORTER_ASSERT_MESSAGE(reporter, !write, "Should not be able to write to a EXTERNAL"
     66                                               " texture.");
     67 }
     68 
     69 static void test_copy_surface(skiatest::Reporter* reporter, GrContext* context,
     70                               GrTexture* externalTexture, uint32_t expectedPixelValues[]) {
     71     GrSurfaceDesc copyDesc;
     72     copyDesc.fConfig = kRGBA_8888_GrPixelConfig;
     73     copyDesc.fWidth = externalTexture->width();
     74     copyDesc.fHeight = externalTexture->height();
     75     copyDesc.fFlags = kRenderTarget_GrSurfaceFlag;
     76     SkAutoTUnref<GrTexture> copy(context->textureProvider()->createTexture(
     77             copyDesc, SkBudgeted::kYes));
     78     context->copySurface(copy, externalTexture);
     79     test_read_pixels(reporter, context, copy, expectedPixelValues);
     80 }
     81 
     82 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(EGLImageTest, reporter, context0, glCtx0) {
     83     // Try to create a second GL context and then check if the contexts have necessary
     84     // extensions to run this test.
     85 
     86     if (kGLES_GrGLStandard != glCtx0->gl()->fStandard) {
     87         return;
     88     }
     89     GrGLGpu* gpu0 = static_cast<GrGLGpu*>(context0->getGpu());
     90     if (!gpu0->glCaps().externalTextureSupport()) {
     91         return;
     92     }
     93 
     94     SkAutoTDelete<SkGLContext> glCtx1 = glCtx0->createNew();
     95     if (!glCtx1) {
     96         return;
     97     }
     98     GrContext* context1 = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)glCtx1->gl());
     99     const GrGLTextureInfo* backendTexture1 = nullptr;
    100     GrEGLImage image = GR_EGL_NO_IMAGE;
    101     GrGLTextureInfo externalTexture;
    102     externalTexture.fID = 0;
    103 
    104     if (!context1) {
    105         cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    106         return;
    107     }
    108 
    109     if (!glCtx1->gl()->hasExtension("EGL_KHR_image") ||
    110         !glCtx1->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
    111         cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    112         return;
    113     }
    114 
    115     ///////////////////////////////// CONTEXT 1 ///////////////////////////////////
    116 
    117     // Use GL Context 1 to create a texture unknown to GrContext.
    118     context1->flush();
    119     GrGpu* gpu1 = context1->getGpu();
    120     static const int kSize = 100;
    121     backendTexture1 = reinterpret_cast<const GrGLTextureInfo*>(
    122         gpu1->createTestingOnlyBackendTexture(nullptr, kSize, kSize, kRGBA_8888_GrPixelConfig));
    123     if (!backendTexture1 || !backendTexture1->fID) {
    124         ERRORF(reporter, "Error creating texture for EGL Image");
    125         cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    126         return;
    127     }
    128     if (GR_GL_TEXTURE_2D != backendTexture1->fTarget) {
    129         ERRORF(reporter, "Expected backend texture to be 2D");
    130         cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    131         return;
    132     }
    133 
    134     // Wrap the texture in an EGLImage
    135     image = glCtx1->texture2DToEGLImage(backendTexture1->fID);
    136     if (GR_EGL_NO_IMAGE == image) {
    137         ERRORF(reporter, "Error creating EGL Image from texture");
    138         cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    139         return;
    140     }
    141 
    142     // Populate the texture using GL context 1. Important to use TexSubImage as TexImage orphans
    143     // the EGL image. Also, this must be done after creating the EGLImage as the texture
    144     // contents may not be preserved when the image is created.
    145     SkAutoTMalloc<uint32_t> pixels(kSize * kSize);
    146     for (int i = 0; i < kSize*kSize; ++i) {
    147         pixels.get()[i] = 0xDDAABBCC;
    148     }
    149     GR_GL_CALL(glCtx1->gl(), ActiveTexture(GR_GL_TEXTURE0));
    150     GR_GL_CALL(glCtx1->gl(), BindTexture(backendTexture1->fTarget, backendTexture1->fID));
    151     GR_GL_CALL(glCtx1->gl(), TexSubImage2D(backendTexture1->fTarget, 0, 0, 0, kSize, kSize,
    152                                            GR_GL_RGBA, GR_GL_UNSIGNED_BYTE, pixels.get()));
    153     GR_GL_CALL(glCtx1->gl(), Finish());
    154     // We've been making direct GL calls in GL context 1, let GrContext 1 know its internal
    155     // state is invalid.
    156     context1->resetContext();
    157 
    158     ///////////////////////////////// CONTEXT 0 ///////////////////////////////////
    159 
    160     // Make a new texture ID in GL Context 0 from the EGL Image
    161     glCtx0->makeCurrent();
    162     externalTexture.fTarget = GR_GL_TEXTURE_EXTERNAL;
    163     externalTexture.fID = glCtx0->eglImageToExternalTexture(image);
    164 
    165     // Wrap this texture ID in a GrTexture
    166     GrBackendTextureDesc externalDesc;
    167     externalDesc.fConfig = kRGBA_8888_GrPixelConfig;
    168     externalDesc.fWidth = kSize;
    169     externalDesc.fHeight = kSize;
    170     externalDesc.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
    171     SkAutoTUnref<GrTexture> externalTextureObj(
    172         context0->textureProvider()->wrapBackendTexture(externalDesc));
    173     if (!externalTextureObj) {
    174         ERRORF(reporter, "Error wrapping external texture in GrTexture.");
    175         cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    176         return;
    177     }
    178 
    179     // Should not be able to wrap as a RT
    180     externalDesc.fFlags = kRenderTarget_GrBackendTextureFlag;
    181     SkAutoTUnref<GrTexture> externalTextureRTObj(
    182         context0->textureProvider()->wrapBackendTexture(externalDesc));
    183     if (externalTextureRTObj) {
    184         ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture as a RT.");
    185     }
    186     externalDesc.fFlags = kNone_GrBackendTextureFlag;
    187 
    188     // Should not be able to wrap with a sample count
    189     externalDesc.fSampleCnt = 4;
    190     SkAutoTUnref<GrTexture> externalTextureMSAAObj(
    191         context0->textureProvider()->wrapBackendTexture(externalDesc));
    192     if (externalTextureMSAAObj) {
    193         ERRORF(reporter, "Should not be able to wrap an EXTERNAL texture with MSAA.");
    194     }
    195     externalDesc.fSampleCnt = 0;
    196 
    197     test_read_pixels(reporter, context0, externalTextureObj, pixels.get());
    198 
    199     test_write_pixels(reporter, context0, externalTextureObj);
    200 
    201     test_copy_surface(reporter, context0, externalTextureObj, pixels.get());
    202 
    203     cleanup(glCtx0, externalTexture.fID, glCtx1, context1, backendTexture1, image);
    204 }
    205 
    206 #endif
    207