1 /* 2 // Copyright(c)2014 IntelCorporation 3 // 4 // LicensedundertheApacheLicense,Version2.0(the"License"); 5 // youmaynotusethisfileexceptincompliancewiththeLicense. 6 // YoumayobtainacopyoftheLicenseat 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unlessrequiredbyapplicablelaworagreedtoinwriting,software 11 // distributedundertheLicenseisdistributedonan"ASIS"BASIS, 12 // WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. 13 // SeetheLicenseforthespecificlanguagegoverningpermissionsand 14 // limitationsundertheLicense. 15 */ 16 #include <gtest/gtest.h> 17 18 #include <binder/IMemory.h> 19 20 #include <gui/ISurfaceComposer.h> 21 #include <gui/Surface.h> 22 #include <gui/SurfaceComposerClient.h> 23 #include <private/gui/ComposerService.h> 24 25 #include <utils/String8.h> 26 27 using namespace android; 28 const char * filename = "/data/my_640x480.nv12"; 29 #define PIXEL_FORMAT_NV12 0x7FA00E00 30 31 // Fill a YV12 buffer with a multi-colored checkerboard pattern 32 void fillYUVBuffer(uint8_t* buf, int w, int h, int stride) { 33 const int blockWidth = w > 16 ? w / 16 : 1; 34 const int blockHeight = h > 16 ? h / 16 : 1; 35 const int yuvTexOffsetY = 0; 36 int yuvTexStrideY = stride; 37 int yuvTexOffsetV = yuvTexStrideY * h; 38 int yuvTexStrideV = (yuvTexStrideY / 2 + 0xf) & ~0xf; 39 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h / 2; 40 int yuvTexStrideU = yuvTexStrideV; 41 for (int x = 0; x < w; x++) { 42 for (int y = 0; y < h; y++) { 43 int parityX = (x / blockWidth) & 1; 44 int parityY = (y / blockHeight) & 1; 45 unsigned char intensity = (parityX ^ parityY) ? 63 : 191; 46 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; 47 if (x < w / 2 && y < h / 2) { 48 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; 49 if (x * 2 < w / 2 && y * 2 < h / 2) { 50 buf[yuvTexOffsetV + (y * 2 * yuvTexStrideV) + x * 2 + 0] = 51 buf[yuvTexOffsetV + (y * 2 * yuvTexStrideV) + x * 2 52 + 1] = 53 buf[yuvTexOffsetV 54 + ((y * 2 + 1) * yuvTexStrideV) 55 + x * 2 + 0] = buf[yuvTexOffsetV 56 + ((y * 2 + 1) * yuvTexStrideV) 57 + x * 2 + 1] = intensity; 58 } 59 } 60 } 61 } 62 } 63 64 void loadYUVBufferFromFile(uint8_t* buf, int w, int h, int stride) { 65 FILE *fp = fopen(filename, "r"); 66 int line = 0; 67 int offset = 0; 68 int buffer_height = h * 1.5; 69 70 if (!fp) { 71 printf("%s: failed to open %s\n", __func__, filename); 72 return; 73 } 74 75 printf("buf=%p, w=%d,h=%d,stride=%d\n", buf, w, h, stride); 76 77 for (line = 0; line < buffer_height; line++) { 78 printf("reading line %d...\n", line); 79 offset = line * stride; 80 fread(buf + offset, w, 1, fp); 81 } 82 83 fclose(fp); 84 } 85 86 int main(int argc, char **argv) { 87 sp < SurfaceControl > sc; 88 sp < Surface > s; 89 sp < ANativeWindow > anw; 90 ANativeWindowBuffer *anb; 91 uint8_t* img = NULL; 92 sp < SurfaceComposerClient > composerClient = new SurfaceComposerClient; 93 if (composerClient->initCheck() != NO_ERROR) 94 return 0; 95 96 sc = composerClient->createSurface(String8("FG Test Surface"), 640, 480, 97 PIXEL_FORMAT_RGBA_8888, 0); 98 if (sc == NULL) 99 return 0;; 100 if (!sc->isValid()) 101 return 0; 102 103 s = sc->getSurface(); 104 anw = s.get(); 105 if (native_window_set_buffers_geometry(anw.get(), 640, 480, 106 PIXEL_FORMAT_NV12) != NO_ERROR) 107 return 0; 108 if (native_window_set_usage(anw.get(), 109 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN) 110 != NO_ERROR) 111 return 0; 112 113 /* 114 * load buffer 115 */ 116 if (native_window_dequeue_buffer_and_wait(anw.get(), &anb)) 117 return 0; 118 if (anb == NULL) 119 return 0; 120 sp <GraphicBuffer> buf(GraphicBuffer::from(anb)); 121 //if (anw->lockBuffer(anw.get(), buf->getNativeBuffer()) != NO_ERROR) 122 // return 0; 123 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**) (&img)); 124 if (!img) { 125 printf("failed to lock buffer\n"); 126 exit(-1); 127 } 128 129 loadYUVBufferFromFile(img, 640, 480, buf->getStride()); 130 buf->unlock(); 131 printf("querying buffer...\n"); 132 if (anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1) != NO_ERROR) 133 return 0; 134 135 // loop it to continuously display?? 136 while (1) { 137 SurfaceComposerClient::openGlobalTransaction(); 138 if (sc->setLayer(INT_MAX - 1) != NO_ERROR) 139 return 0; 140 if (sc->show() != NO_ERROR) 141 return 0; 142 143 SurfaceComposerClient::closeGlobalTransaction(); 144 } 145 return 0; 146 } 147 148