| /* |
| // Copyright (c) 2014 Intel Corporation |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| */ |
| #include <gtest/gtest.h> |
| |
| #include <binder/IMemory.h> |
| |
| #include <gui/ISurfaceComposer.h> |
| #include <gui/Surface.h> |
| #include <gui/SurfaceComposerClient.h> |
| #include <private/gui/ComposerService.h> |
| |
| #include <utils/String8.h> |
| |
| using namespace android; |
| const char * filename = "/data/my_640x480.nv12"; |
| #define PIXEL_FORMAT_NV12 0x7FA00E00 |
| |
| // Fill a YV12 buffer with a multi-colored checkerboard pattern |
| void fillYUVBuffer(uint8_t* buf, int w, int h, int stride) { |
| const int blockWidth = w > 16 ? w / 16 : 1; |
| const int blockHeight = h > 16 ? h / 16 : 1; |
| const int yuvTexOffsetY = 0; |
| int yuvTexStrideY = stride; |
| int yuvTexOffsetV = yuvTexStrideY * h; |
| int yuvTexStrideV = (yuvTexStrideY / 2 + 0xf) & ~0xf; |
| int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h / 2; |
| int yuvTexStrideU = yuvTexStrideV; |
| for (int x = 0; x < w; x++) { |
| for (int y = 0; y < h; y++) { |
| int parityX = (x / blockWidth) & 1; |
| int parityY = (y / blockHeight) & 1; |
| unsigned char intensity = (parityX ^ parityY) ? 63 : 191; |
| buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; |
| if (x < w / 2 && y < h / 2) { |
| buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; |
| if (x * 2 < w / 2 && y * 2 < h / 2) { |
| buf[yuvTexOffsetV + (y * 2 * yuvTexStrideV) + x * 2 + 0] = |
| buf[yuvTexOffsetV + (y * 2 * yuvTexStrideV) + x * 2 |
| + 1] = |
| buf[yuvTexOffsetV |
| + ((y * 2 + 1) * yuvTexStrideV) |
| + x * 2 + 0] = buf[yuvTexOffsetV |
| + ((y * 2 + 1) * yuvTexStrideV) |
| + x * 2 + 1] = intensity; |
| } |
| } |
| } |
| } |
| } |
| |
| void loadYUVBufferFromFile(uint8_t* buf, int w, int h, int stride) { |
| FILE *fp = fopen(filename, "r"); |
| int line = 0; |
| int offset = 0; |
| int buffer_height = h * 1.5; |
| |
| if (!fp) { |
| printf("%s: failed to open %s\n", __func__, filename); |
| return; |
| } |
| |
| printf("buf=%p, w=%d,h=%d,stride=%d\n", buf, w, h, stride); |
| |
| for (line = 0; line < buffer_height; line++) { |
| printf("reading line %d...\n", line); |
| offset = line * stride; |
| fread(buf + offset, w, 1, fp); |
| } |
| |
| fclose(fp); |
| } |
| |
| int main(int argc, char **argv) { |
| sp < SurfaceControl > sc; |
| sp < Surface > s; |
| sp < ANativeWindow > anw; |
| ANativeWindowBuffer *anb; |
| uint8_t* img = NULL; |
| sp < SurfaceComposerClient > composerClient = new SurfaceComposerClient; |
| if (composerClient->initCheck() != NO_ERROR) |
| return 0; |
| |
| sc = composerClient->createSurface(String8("FG Test Surface"), 640, 480, |
| PIXEL_FORMAT_RGBA_8888, 0); |
| if (sc == NULL) |
| return 0;; |
| if (!sc->isValid()) |
| return 0; |
| |
| s = sc->getSurface(); |
| anw = s.get(); |
| if (native_window_set_buffers_geometry(anw.get(), 640, 480, |
| PIXEL_FORMAT_NV12) != NO_ERROR) |
| return 0; |
| if (native_window_set_usage(anw.get(), |
| GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN) |
| != NO_ERROR) |
| return 0; |
| |
| /* |
| * load buffer |
| */ |
| if (native_window_dequeue_buffer_and_wait(anw.get(), &anb)) |
| return 0; |
| if (anb == NULL) |
| return 0; |
| sp < GraphicBuffer > buf(new GraphicBuffer(anb, false)); |
| //if (anw->lockBuffer(anw.get(), buf->getNativeBuffer()) != NO_ERROR) |
| // return 0; |
| buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**) (&img)); |
| if (!img) { |
| printf("failed to lock buffer\n"); |
| exit(-1); |
| } |
| |
| loadYUVBufferFromFile(img, 640, 480, buf->getStride()); |
| buf->unlock(); |
| printf("querying buffer...\n"); |
| if (anw->queueBuffer(anw.get(), buf->getNativeBuffer(), -1) != NO_ERROR) |
| return 0; |
| |
| // loop it to continuously display?? |
| while (1) { |
| SurfaceComposerClient::openGlobalTransaction(); |
| if (sc->setLayer(INT_MAX - 1) != NO_ERROR) |
| return 0; |
| if (sc->show() != NO_ERROR) |
| return 0; |
| |
| SurfaceComposerClient::closeGlobalTransaction(); |
| } |
| return 0; |
| } |
| |