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