1 /* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "FillBuffer.h" 18 19 #include <ui/GraphicBuffer.h> 20 21 #include <gtest/gtest.h> 22 23 namespace android { 24 25 void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) { 26 const int blockWidth = w > 16 ? w / 16 : 1; 27 const int blockHeight = h > 16 ? h / 16 : 1; 28 const int yuvTexOffsetY = 0; 29 int yuvTexStrideY = stride; 30 int yuvTexOffsetV = yuvTexStrideY * h; 31 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 32 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; 33 int yuvTexStrideU = yuvTexStrideV; 34 for (int x = 0; x < w; x++) { 35 for (int y = 0; y < h; y++) { 36 int parityX = (x / blockWidth) & 1; 37 int parityY = (y / blockHeight) & 1; 38 unsigned char intensity = (parityX ^ parityY) ? 63 : 191; 39 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; 40 if (x < w / 2 && y < h / 2) { 41 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; 42 if (x * 2 < w / 2 && y * 2 < h / 2) { 43 buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] = 44 buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] = 45 buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] = 46 buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = 47 intensity; 48 } 49 } 50 } 51 } 52 } 53 54 void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride, 55 const android_native_rect_t& rect) { 56 const int yuvTexOffsetY = 0; 57 int yuvTexStrideY = stride; 58 int yuvTexOffsetV = yuvTexStrideY * h; 59 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 60 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; 61 int yuvTexStrideU = yuvTexStrideV; 62 for (int x = 0; x < w; x++) { 63 for (int y = 0; y < h; y++) { 64 bool inside = rect.left <= x && x < rect.right && 65 rect.top <= y && y < rect.bottom; 66 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64; 67 if (x < w / 2 && y < h / 2) { 68 bool inside = rect.left <= 2*x && 2*x < rect.right && 69 rect.top <= 2*y && 2*y < rect.bottom; 70 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16; 71 buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = 72 inside ? 16 : 255; 73 } 74 } 75 } 76 } 77 78 void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) { 79 const size_t PIXEL_SIZE = 4; 80 for (int x = 0; x < w; x++) { 81 for (int y = 0; y < h; y++) { 82 off_t offset = (y * stride + x) * PIXEL_SIZE; 83 for (int c = 0; c < 4; c++) { 84 int parityX = (x / (1 << (c+2))) & 1; 85 int parityY = (y / (1 << (c+2))) & 1; 86 buf[offset + c] = (parityX ^ parityY) ? 231 : 35; 87 } 88 } 89 } 90 } 91 92 void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) { 93 android_native_buffer_t* anb; 94 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), 95 &anb)); 96 ASSERT_TRUE(anb != NULL); 97 98 sp<GraphicBuffer> buf(GraphicBuffer::from(anb)); 99 100 uint8_t* img = NULL; 101 ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, 102 (void**)(&img))); 103 fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride()); 104 ASSERT_EQ(NO_ERROR, buf->unlock()); 105 ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer(), 106 -1)); 107 } 108 } // namespace android 109