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 
     91 #define LOG_TAG "hwcColorEquivTest"
     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_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     unsigned int pass;
    171     char cmd[MAXCMD];
    172     string str;
    173 
    174     testSetLogCatTag(LOG_TAG);
    175 
    176     assert(refFormat != NULL);
    177 
    178     testSetLogCatTag(LOG_TAG);
    179 
    180     // Parse command line arguments
    181     while ((opt = getopt(argc, argv, "vs:e:r:D:?h")) != -1) {
    182         switch (opt) {
    183           case 'D': // End of test delay
    184                     // Delay between completion of final pass and restart
    185                     // of framework
    186             endDelay = strtod(optarg, &chptr);
    187             if ((*chptr != '\0') || (endDelay < 0.0)) {
    188                 testPrintE("Invalid command-line specified end of test delay "
    189                            "of: %s", optarg);
    190                 exit(1);
    191             }
    192             break;
    193 
    194           case 's': // Starting reference color
    195             str = optarg;
    196             while (optind < argc) {
    197                 if (*argv[optind] == '-') { break; }
    198                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
    199                 if ((endChar == '>') || (endChar == ']')) { break; }
    200                 str += " " + string(argv[optind++]);
    201             }
    202             {
    203                 istringstream in(str);
    204                 startRefColor = hwcTestParseColor(in, error);
    205                 // Any parse error or characters not used by parser
    206                 if (error
    207                     || (((unsigned int) in.tellg() != in.str().length())
    208                         && (in.tellg() != (streampos) -1))) {
    209                     testPrintE("Invalid command-line specified start "
    210                                "reference color of: %s", str.c_str());
    211                     exit(2);
    212                 }
    213             }
    214             break;
    215 
    216           case 'e': // Ending reference color
    217             str = optarg;
    218             while (optind < argc) {
    219                 if (*argv[optind] == '-') { break; }
    220                 char endChar = (str.length() > 1) ? str[str.length() - 1] : 0;
    221                 if ((endChar == '>') || (endChar == ']')) { break; }
    222                 str += " " + string(argv[optind++]);
    223             }
    224             {
    225                 istringstream in(str);
    226                 endRefColor = hwcTestParseColor(in, error);
    227                 // Any parse error or characters not used by parser
    228                 if (error
    229                     || (((unsigned int) in.tellg() != in.str().length())
    230                         && (in.tellg() != (streampos) -1))) {
    231                     testPrintE("Invalid command-line specified end "
    232                                "reference color of: %s", str.c_str());
    233                     exit(3);
    234                 }
    235             }
    236             break;
    237 
    238           case 'r': // Reference graphic format
    239             refFormat = hwcTestGraphicFormatLookup(optarg);
    240             if (refFormat == NULL) {
    241                 testPrintE("Unkown command-line specified reference graphic "
    242                            "format of: %s", optarg);
    243                 printSyntax(basename(argv[0]));
    244                 exit(4);
    245             }
    246             break;
    247 
    248           case 'v': // Verbose
    249             verbose = true;
    250             break;
    251 
    252           case 'h': // Help
    253           case '?':
    254           default:
    255             printSyntax(basename(argv[0]));
    256             exit(((optopt == 0) || (optopt == '?')) ? 0 : 5);
    257         }
    258     }
    259 
    260     // Expect a single positional parameter, which specifies the
    261     // equivalence graphic format.
    262     if (argc != (optind + 1)) {
    263         testPrintE("Expected a single command-line postional parameter");
    264         printSyntax(basename(argv[0]));
    265         exit(6);
    266     }
    267     equivFormat = hwcTestGraphicFormatLookup(argv[optind]);
    268     if (equivFormat == NULL) {
    269         testPrintE("Unkown command-line specified equivalence graphic "
    270                    "format of: %s", argv[optind]);
    271         printSyntax(basename(argv[0]));
    272         exit(7);
    273     }
    274 
    275     testPrintI("refFormat: %u %s", refFormat->format, refFormat->desc);
    276     testPrintI("equivFormat: %u %s", equivFormat->format, equivFormat->desc);
    277     testPrintI("startRefColor: %s", ((string) startRefColor).c_str());
    278     testPrintI("endRefColor: %s", ((string) endRefColor).c_str());
    279     testPrintI("endDelay: %f", endDelay);
    280 
    281     // Stop framework
    282     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_STOP_FRAMEWORK);
    283     if (rv >= (signed) sizeof(cmd) - 1) {
    284         testPrintE("Command too long for: %s", CMD_STOP_FRAMEWORK);
    285         exit(8);
    286     }
    287     testExecCmd(cmd);
    288     testDelay(1.0); // TODO - needs means to query whether asynchronous stop
    289                     // framework operation has completed.  For now, just wait
    290                     // a long time.
    291 
    292     init();
    293 
    294     // Use the upper third of the display for the reference frame and
    295     // the middle third for the equivalence frame.
    296     unsigned int refHeight = height / 3;
    297     unsigned int refPosY = 0; // Reference frame Y position
    298     unsigned int refPosX = 0; // Reference frame X position
    299     unsigned int refWidth = width - refPosX;
    300     if ((refWidth & refFormat->wMod) != 0) {
    301         refWidth += refFormat->wMod - (refWidth % refFormat->wMod);
    302     }
    303     unsigned int equivHeight = height / 3;
    304     unsigned int equivPosY = refHeight; // Equivalence frame Y position
    305     unsigned int equivPosX = 0;         // Equivalence frame X position
    306     unsigned int equivWidth = width - equivPosX;
    307     if ((equivWidth & equivFormat->wMod) != 0) {
    308         equivWidth += equivFormat->wMod - (equivWidth % equivFormat->wMod);
    309     }
    310 
    311     // Create reference and equivalence graphic buffers
    312     const unsigned int numFrames = 2;
    313     sp<GraphicBuffer> refFrame;
    314     refFrame = new GraphicBuffer(refWidth, refHeight,
    315                                  refFormat->format, texUsage);
    316     if ((rv = refFrame->initCheck()) != NO_ERROR) {
    317         testPrintE("refFrame initCheck failed, rv: %i", rv);
    318         testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
    319                    refFormat->format,
    320                    hwcTestGraphicFormat2str(refFormat->format));
    321         exit(9);
    322     }
    323     testPrintI("refFrame width: %u height: %u format: %u %s",
    324                refWidth, refHeight, refFormat->format,
    325                hwcTestGraphicFormat2str(refFormat->format));
    326 
    327     sp<GraphicBuffer> equivFrame;
    328     equivFrame = new GraphicBuffer(equivWidth, equivHeight,
    329                                    equivFormat->format, texUsage);
    330     if ((rv = refFrame->initCheck()) != NO_ERROR) {
    331         testPrintE("refFrame initCheck failed, rv: %i", rv);
    332         testPrintE("  width %u height: %u format: %u %s", refWidth, refHeight,
    333                    refFormat->format,
    334                    hwcTestGraphicFormat2str(refFormat->format));
    335         exit(10);
    336     }
    337     testPrintI("equivFrame width: %u height: %u format: %u %s",
    338                equivWidth, equivHeight, equivFormat->format,
    339                hwcTestGraphicFormat2str(equivFormat->format));
    340 
    341     // Fill the frames with a horizontal blend
    342     hwcTestFillColorHBlend(refFrame.get(), refFormat->format,
    343                            startRefColor, endRefColor);
    344     hwcTestFillColorHBlend(equivFrame.get(), refFormat->format,
    345                            startRefColor, endRefColor);
    346 
    347     hwc_layer_list_t *list;
    348     size_t size = sizeof(hwc_layer_list) + numFrames * sizeof(hwc_layer_t);
    349     if ((list = (hwc_layer_list_t *) calloc(1, size)) == NULL) {
    350         testPrintE("Allocate list failed");
    351         exit(11);
    352     }
    353     list->flags = HWC_GEOMETRY_CHANGED;
    354     list->numHwLayers = numFrames;
    355 
    356     hwc_layer_t *layer = &list->hwLayers[0];
    357     layer->handle = refFrame->handle;
    358     layer->blending = HWC_BLENDING_NONE;
    359     layer->sourceCrop.left = 0;
    360     layer->sourceCrop.top = 0;
    361     layer->sourceCrop.right = width;
    362     layer->sourceCrop.bottom = refHeight;
    363     layer->displayFrame.left = 0;
    364     layer->displayFrame.top = 0;
    365     layer->displayFrame.right = width;
    366     layer->displayFrame.bottom = refHeight;
    367     layer->visibleRegionScreen.numRects = 1;
    368     layer->visibleRegionScreen.rects = &layer->displayFrame;
    369 
    370     layer++;
    371     layer->handle = equivFrame->handle;
    372     layer->blending = HWC_BLENDING_NONE;
    373     layer->sourceCrop.left = 0;
    374     layer->sourceCrop.top = 0;
    375     layer->sourceCrop.right = width;
    376     layer->sourceCrop.bottom = equivHeight;
    377     layer->displayFrame.left = 0;
    378     layer->displayFrame.top = refHeight;
    379     layer->displayFrame.right = width;
    380     layer->displayFrame.bottom = layer->displayFrame.top + equivHeight;
    381     layer->visibleRegionScreen.numRects = 1;
    382     layer->visibleRegionScreen.rects = &layer->displayFrame;
    383 
    384     // Perform prepare operation
    385     if (verbose) { testPrintI("Prepare:"); hwcTestDisplayList(list); }
    386     hwcDevice->prepare(hwcDevice, list);
    387     if (verbose) {
    388         testPrintI("Post Prepare:");
    389         hwcTestDisplayListPrepareModifiable(list);
    390     }
    391 
    392     // Turn off the geometry changed flag
    393     list->flags &= ~HWC_GEOMETRY_CHANGED;
    394 
    395     if (verbose) {hwcTestDisplayListHandles(list); }
    396     hwcDevice->set(hwcDevice, dpy, surface, list);
    397 
    398     testDelay(endDelay);
    399 
    400     // Start framework
    401     rv = snprintf(cmd, sizeof(cmd), "%s", CMD_START_FRAMEWORK);
    402     if (rv >= (signed) sizeof(cmd) - 1) {
    403         testPrintE("Command too long for: %s", CMD_START_FRAMEWORK);
    404         exit(12);
    405     }
    406     testExecCmd(cmd);
    407 
    408     return 0;
    409 }
    410 
    411 void init(void)
    412 {
    413     // Seed pseudo random number generator
    414     // Seeding causes fill horizontal blend to fill the pad area with
    415     // a deterministic set of values.
    416     srand48(0);
    417 
    418     hwcTestInitDisplay(verbose, &dpy, &surface, &width, &height);
    419 
    420     hwcTestOpenHwc(&hwcDevice);
    421 }
    422 
    423 void printSyntax(const char *cmd)
    424 {
    425     testPrintE("  %s [options] graphicFormat", cmd);
    426     testPrintE("    options:");
    427     testPrintE("      -s <0.##, 0.##, 0.##> - Starting reference color");
    428     testPrintE("      -e <0.##, 0.##, 0.##> - Ending reference color");
    429     testPrintE("      -r format - Reference graphic format");
    430     testPrintE("      -D #.## - End of test delay");
    431     testPrintE("      -v Verbose");
    432     testPrintE("");
    433     testPrintE("    graphic formats:");
    434     for (unsigned int n1 = 0; n1 < NUMA(hwcTestGraphicFormat); n1++) {
    435         testPrintE("      %s", hwcTestGraphicFormat[n1].desc);
    436     }
    437 }
    438