Home | History | Annotate | Download | only in hwc
      1 /*
      2  * Copyright (C) 2011 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 
     18 /*
     19  * Hardware Composer Color Equivalence
     20  *
     21  * Synopsis
     22  *   hwc_colorequiv [options] eFmt
     23  *
     24  *     options:
     25          -v - verbose
     26  *       -s <0.##, 0.##, 0.##> - Start color (default: <0.0, 0.0, 0.0>
     27  *       -e <0.##, 0.##, 0.##> - Ending color (default: <1.0, 1.0, 1.0>
     28  *       -r fmt - reference graphic format
     29  *       -D #.## - End of test delay
     30  *
     31  *     graphic formats:
     32  *       RGBA8888 (reference frame default)
     33  *       RGBX8888
     34  *       RGB888
     35  *       RGB565
     36  *       BGRA8888
     37  *       RGBA5551
     38  *       RGBA4444
     39  *       YV12
     40  *
     41  * Description
     42  *   Renders a horizontal blend in two frames.  The first frame is rendered
     43  *   in the upper third of the display and is called the reference frame.
     44  *   The second frame is displayed in the middle third and is called the
     45  *   equivalence frame.  The primary purpose of this utility is to verify
     46  *   that the colors produced in the reference and equivalence frames are
     47  *   the same.  The colors are the same when the colors are the same
     48  *   vertically between the reference and equivalence frames.
     49  *
     50  *   By default the reference frame is rendered through the use of the
     51  *   RGBA8888 graphic format.  The -r option can be used to specify a
     52  *   non-default reference frame graphic format.  The graphic format of
     53  *   the equivalence frame is determined by a single required positional
     54  *   parameter.  Intentionally there is no default for the graphic format
     55  *   of the equivalence frame.
     56  *
     57  *   The horizontal blend in the reference frame is produced from a linear
     58  *   interpolation from a start color (default: <0.0, 0.0, 0.0> on the left
     59  *   side to an end color (default <1.0, 1.0, 1.0> on the right side.  Where
     60  *   possible the equivalence frame is rendered with the equivalent color
     61  *   from the reference frame.  A color of black is used in the equivalence
     62  *   frame for cases where an equivalent color does not exist.
     63  */
     64 
     65 #define LOG_TAG "hwcColorEquivTest"
     66 
     67 #include <algorithm>
     68 #include <assert.h>
     69 #include <cerrno>
     70 #include <cmath>
     71 #include <cstdlib>
     72 #include <ctime>
     73 #include <libgen.h>
     74 #include <sched.h>
     75 #include <sstream>
     76 #include <stdint.h>
     77 #include <string.h>
     78 #include <unistd.h>
     79 #include <vector>
     80 
     81 #include <sys/syscall.h>
     82 #include <sys/types.h>
     83 #include <sys/wait.h>
     84 
     85 #include <EGL/egl.h>
     86 #include <EGL/eglext.h>
     87 #include <GLES2/gl2.h>
     88 #include <GLES2/gl2ext.h>
     89 
     90 #include <ui/GraphicBuffer.h>
     91 
     92 #include <utils/Log.h>
     93 #include <testUtil.h>
     94 
     95 #include <hardware/hwcomposer.h>
     96 
     97 #include "hwcTestLib.h"
     98 
     99 using namespace std;
    100 using namespace android;
    101 
    102 // Defaults for command-line options
    103 const bool defaultVerbose = false;
    104 const ColorFract defaultStartColor(0.0, 0.0, 0.0);
    105 const ColorFract defaultEndColor(1.0, 1.0, 1.0);
    106 const char *defaultRefFormat = "RGBA8888";
    107 const float defaultEndDelay = 2.0; // Default delay after rendering graphics
    108 
    109 // Defines
    110 #define MAXSTR               100
    111 #define MAXCMD               200
    112 #define BITSPERBYTE            8 // TODO: Obtain from <values.h>, once
    113                                  // it has been added
    114 
    115 #define CMD_STOP_FRAMEWORK   "stop 2>&1"
    116 #define CMD_START_FRAMEWORK  "start 2>&1"
    117 
    118 // Macros
    119 #define NUMA(a) (sizeof(a) / sizeof((a)[0])) // Num elements in an array
    120 #define MEMCLR(addr, size) do { \
    121         memset((addr), 0, (size)); \
    122     } while (0)
    123 
    124 // Globals
    125 static const int texUsage = GraphicBuffer::USAGE_HW_TEXTURE |
    126         GraphicBuffer::USAGE_SW_WRITE_RARELY;
    127 static hwc_composer_device_1_t *hwcDevice;
    128 static EGLDisplay dpy;
    129 static EGLSurface surface;
    130 static EGLint width, height;
    131 
    132 // Functions prototypes
    133 void init(void);
    134 void printSyntax(const char *cmd);
    135 
    136 // Command-line option settings
    137 static bool verbose = defaultVerbose;
    138 static ColorFract startRefColor = defaultStartColor;
    139 static ColorFract endRefColor = defaultEndColor;
    140 static float endDelay = defaultEndDelay;
    141 static const struct hwcTestGraphicFormat *refFormat
    142     = hwcTestGraphicFormatLookup(defaultRefFormat);
    143 static const struct hwcTestGraphicFormat *equivFormat;
    144 
    145 /*
    146  * Main
    147  *
    148  * Performs the following high-level sequence of operations:
    149  *
    150  *   1. Command-line parsing
    151  *
    152  *   2. Stop framework
    153  *
    154  *   3. Initialization
    155  *
    156  *   4. Create Hardware Composer description of reference and equivalence frames
    157  *
    158  *   5. Have Hardware Composer render the reference and equivalence frames
    159  *
    160  *   6. Delay for amount of time given by endDelay
    161  *
    162  *   7. Start framework
    163  */
    164 int
    165 main(int argc, char *argv[])
    166 {
    167     int rv, opt;
    168     bool error;
    169     char *chptr;
    170     char cmd[MAXCMD];
    171     string str;
    172 
    173     testSetLogCatTag(LOG_TAG);
    174 
    175     assert(refFormat != NULL);
    176 
    177     testSetLogCatTag(LOG_TAG);
    178 
    179     // Parse command line arguments
    180     while ((opt = getopt(argc, argv, "vs:e:r:D:?h")) != -1) {
    181         switch (opt) {
    182           case 'D': // End of test delay
    183                     // Delay between completion of final pass and restart
    184                     // of framework
    185             endDelay = strtod(optarg, &chptr);
    186             if ((*chptr != '\0') || (endDelay < 0.0)) {
    187                 testPrintE("Invalid command-line specified end of test delay "
    188                            "of: %s", optarg);
    189                 exit(1);
    190             }
    191             break;
    192 
    193           case 's': // Starting reference color
    194             str = optarg;
    195             while (optind < argc) {
    196                 if (*argv[optind] == '-') { break; }
    197                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
    198                 if ((endChar == '>') || (endChar == ']')) { break; }
    199                 str += " " + string(argv[optind++]);
    200             }
    201             {
    202                 istringstream in(str);
    203                 startRefColor = hwcTestParseColor(in, error);
    204                 // Any parse error or characters not used by parser
    205                 if (error
    206                     || (((unsigned int) in.tellg() != in.str().length())
    207                         && (in.tellg() != (streampos) -1))) {
    208                     testPrintE("Invalid command-line specified start "
    209                                "reference color of: %s", str.c_str());
    210                     exit(2);
    211                 }
    212             }
    213             break;
    214 
    215           case 'e': // Ending reference color
    216             str = optarg;
    217             while (optind < argc) {
    218                 if (*argv[optind] == '-') { break; }
    219                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
    220                 if ((endChar == '>') || (endChar == ']')) { break; }
    221                 str += " " + string(argv[optind++]);
    222             }
    223             {
    224                 istringstream in(str);
    225                 endRefColor = hwcTestParseColor(in, error);
    226                 // Any parse error or characters not used by parser
    227                 if (error
    228                     || (((unsigned int) in.tellg() != in.str().length())
    229                         && (in.tellg() != (streampos) -1))) {
    230                     testPrintE("Invalid command-line specified end "
    231                                "reference color of: %s", str.c_str());
    232                     exit(3);
    233                 }
    234             }
    235             break;
    236 
    237           case 'r': // Reference graphic format
    238             refFormat = hwcTestGraphicFormatLookup(optarg);
    239             if (refFormat == NULL) {
    240                 testPrintE("Unkown command-line specified reference graphic "
    241                            "format of: %s", optarg);
    242                 printSyntax(basename(argv[0]));
    243                 exit(4);
    244             }
    245             break;
    246 
    247           case 'v': // Verbose
    248             verbose = true;
    249             break;
    250 
    251           case 'h': // Help
    252           case '?':
    253           default:
    254             printSyntax(basename(argv[0]));
    255             exit(((optopt == 0) || (optopt == '?')) ? 0 : 5);
    256         }
    257     }
    258 
    259     // Expect a single positional parameter, which specifies the
    260     // equivalence graphic format.
    261     if (argc != (optind + 1)) {
    262         testPrintE("Expected a single command-line postional parameter");
    263         printSyntax(basename(argv[0]));
    264         exit(6);
    265     }
    266     equivFormat = hwcTestGraphicFormatLookup(argv[optind]);
    267     if (equivFormat == NULL) {
    268         testPrintE("Unkown command-line specified equivalence graphic "
    269                    "format of: %s", argv[optind]);
    270         printSyntax(basename(argv[0]));
    271         exit(7);
    272     }
    273 
    274     testPrintI("refFormat: %u %s", refFormat->format, refFormat->desc);
    275     testPrintI("equivFormat: %u %s", equivFormat->format, equivFormat->desc);
    276     testPrintI("startRefColor: %s", ((string) startRefColor).c_str());
    277     testPrintI("endRefColor: %s", ((string) endRefColor).c_str());
    278     testPrintI("endDelay: %f", endDelay);
    279 
    280     // Stop framework
    281     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
    282     if (rv >= (signed) sizeof(cmd) - 1) {
    283         testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
    284         exit(8);
    285     }
    286     testExecCmd(cmd);
    287     testDelay(1.0); // TODO - needs means to query whether asynchronous stop
    288                     // framework operation has completed.  For now, just wait
    289                     // a long time.
    290 
    291     init();
    292 
    293     // Use the upper third of the display for the reference frame and
    294     // the middle third for the equivalence frame.
    295     unsigned int refHeight = height / 3;
    296     unsigned int refPosX = 0; // Reference frame X position
    297     unsigned int refWidth = width - refPosX;
    298     if ((refWidth & refFormat->wMod) != 0) {
    299         refWidth += refFormat->wMod - (refWidth % refFormat->wMod);
    300     }
    301     unsigned int equivHeight = height / 3;
    302     unsigned int equivPosX = 0;         // Equivalence frame X position
    303     unsigned int equivWidth = width - equivPosX;
    304     if ((equivWidth & equivFormat->wMod) != 0) {
    305         equivWidth += equivFormat->wMod - (equivWidth % equivFormat->wMod);
    306     }
    307 
    308     // Create reference and equivalence graphic buffers
    309     const unsigned int numFrames = 2;
    310     sp<GraphicBuffer> refFrame;
    311     refFrame = new GraphicBuffer(refWidth, refHeight,
    312                                  refFormat->format, texUsage);
    313     if ((rv = refFrame->initCheck()) != NO_ERROR) {
    314         testPrintE("refFrame initCheck failed, rv: %i", rv);
    315         testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
    316                    refFormat->format,
    317                    hwcTestGraphicFormat2str(refFormat->format));
    318         exit(9);
    319     }
    320     testPrintI("refFrame width: %u height: %u format: %u %s",
    321                refWidth, refHeight, refFormat->format,
    322                hwcTestGraphicFormat2str(refFormat->format));
    323 
    324     sp<GraphicBuffer> equivFrame;
    325     equivFrame = new GraphicBuffer(equivWidth, equivHeight,
    326                                    equivFormat->format, texUsage);
    327     if ((rv = refFrame->initCheck()) != NO_ERROR) {
    328         testPrintE("refFrame initCheck failed, rv: %i", rv);
    329         testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
    330                    refFormat->format,
    331                    hwcTestGraphicFormat2str(refFormat->format));
    332         exit(10);
    333     }
    334     testPrintI("equivFrame width: %u height: %u format: %u %s",
    335                equivWidth, equivHeight, equivFormat->format,
    336                hwcTestGraphicFormat2str(equivFormat->format));
    337 
    338     // Fill the frames with a horizontal blend
    339     hwcTestFillColorHBlend(refFrame.get(), refFormat->format,
    340                            startRefColor, endRefColor);
    341     hwcTestFillColorHBlend(equivFrame.get(), refFormat->format,
    342                            startRefColor, endRefColor);
    343 
    344     hwc_display_contents_1_t *list;
    345     size_t size = sizeof(hwc_display_contents_1_t) + numFrames * sizeof(hwc_layer_1_t);
    346     if ((list = (hwc_display_contents_1_t *) calloc(1, size)) == NULL) {
    347         testPrintE("Allocate list failed");
    348         exit(11);
    349     }
    350     list->flags = HWC_GEOMETRY_CHANGED;
    351     list->numHwLayers = numFrames;
    352 
    353     hwc_layer_1_t *layer = &list->hwLayers[0];
    354     layer->handle = refFrame->handle;
    355     layer->blending = HWC_BLENDING_NONE;
    356     layer->sourceCrop.left = 0;
    357     layer->sourceCrop.top = 0;
    358     layer->sourceCrop.right = width;
    359     layer->sourceCrop.bottom = refHeight;
    360     layer->displayFrame.left = 0;
    361     layer->displayFrame.top = 0;
    362     layer->displayFrame.right = width;
    363     layer->displayFrame.bottom = refHeight;
    364     layer->visibleRegionScreen.numRects = 1;
    365     layer->visibleRegionScreen.rects = &layer->displayFrame;
    366 
    367     layer++;
    368     layer->handle = equivFrame->handle;
    369     layer->blending = HWC_BLENDING_NONE;
    370     layer->sourceCrop.left = 0;
    371     layer->sourceCrop.top = 0;
    372     layer->sourceCrop.right = width;
    373     layer->sourceCrop.bottom = equivHeight;
    374     layer->displayFrame.left = 0;
    375     layer->displayFrame.top = refHeight;
    376     layer->displayFrame.right = width;
    377     layer->displayFrame.bottom = layer->displayFrame.top + equivHeight;
    378     layer->visibleRegionScreen.numRects = 1;
    379     layer->visibleRegionScreen.rects = &layer->displayFrame;
    380 
    381     // Perform prepare operation
    382     if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
    383     hwcDevice->prepare(hwcDevice, 1, &list);
    384     if (verbose) {
    385         testPrintI("Post Prepare:");
    386         hwcTestDisplayListPrepareModifiable(list);
    387     }
    388 
    389     // Turn off the geometry changed flag
    390     list->flags &= ~HWC_GEOMETRY_CHANGED;
    391 
    392     if (verbose) {hwcTestDisplayListHandles(list); }
    393     list->dpy = dpy;
    394     list->sur = surface;
    395     hwcDevice->set(hwcDevice, 1, &list);
    396 
    397     testDelay(endDelay);
    398 
    399     // Start framework
    400     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
    401     if (rv >= (signed) sizeof(cmd) - 1) {
    402         testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
    403         exit(12);
    404     }
    405     testExecCmd(cmd);
    406 
    407     return 0;
    408 }
    409 
    410 void init(void)
    411 {
    412     // Seed pseudo random number generator
    413     // Seeding causes fill horizontal blend to fill the pad area with
    414     // a deterministic set of values.
    415     srand48(0);
    416 
    417     hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
    418 
    419     hwcTestOpenHwc(&hwcDevice);
    420 }
    421 
    422 void printSyntax(const char *cmd)
    423 {
    424     testPrintE("  %s [options] graphicFormat", cmd);
    425     testPrintE("    options:");
    426     testPrintE("      -s <0.##, 0.##, 0.##> - Starting reference color");
    427     testPrintE("      -e <0.##, 0.##, 0.##> - Ending reference color");
    428     testPrintE("      -r format - Reference graphic format");
    429     testPrintE("      -D #.## - End of test delay");
    430     testPrintE("      -v Verbose");
    431     testPrintE("");
    432     testPrintE("    graphic formats:");
    433     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
    434         testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
    435     }
    436 }
    437