1eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman/* 2eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman * Copyright 2017 Google Inc. 3eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman * 4eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman * Use of this source code is governed by a BSD-style license that can be 5eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman * found in the LICENSE file. 6eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman */ 7eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 8eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#include "SkTypes.h" 9eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 10eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#include "SkCanvas.h" 11eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#include "SkSurface.h" 12eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 13eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#if SK_SUPPORT_GPU 14eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 15eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#include "GrContext.h" 16eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#include "GrTest.h" 17eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#include "Test.h" 18eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 19eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osmanstatic SkBitmap read_pixels(sk_sp<SkSurface> surface) { 20eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkBitmap bmp; 21eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman bmp.allocN32Pixels(surface->width(), surface->height()); 22f19421961c59ceabfb88a5c5cdf7c7e31a95b015Mike Reed if (!surface->readPixels(bmp, 0, 0)) { 23eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkDebugf("readPixels failed\n"); 24eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman } 25eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman return bmp; 26eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman} 27eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 28eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osmanstatic sk_sp<SkSurface> make_surface(GrContext* context) { 29eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkImageInfo info = SkImageInfo::Make(50, 50, kRGBA_8888_SkColorType, kPremul_SkAlphaType); 30eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman return SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info, 4, 31eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman kBottomLeft_GrSurfaceOrigin, nullptr); 32eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman} 33eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 34eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman// Tests that readPixels returns up-to-date results. Demonstrates a bug on Galaxy S6 35eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman// (Mali T760), in MSAA mode. 36eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian OsmanDEF_GPUTEST_FOR_RENDERING_CONTEXTS(skbug6653, reporter, ctxInfo) { 37eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman GrContext* ctx = ctxInfo.grContext(); 38eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkRect rect = SkRect::MakeWH(50, 50); 39eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 40eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkPaint paint; 41eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman paint.setColor(SK_ColorWHITE); 42eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman paint.setStrokeWidth(5); 43eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman paint.setStyle(SkPaint::kStroke_Style); 44eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 45eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // The one device that fails this test (Galaxy S6) does so in a flaky fashion. Trying many 46eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // times makes it more likely to fail. Also, interacting with the phone (eg swiping between 47eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // different home screens) while the test is running makes it fail close to 100%. 48eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman static const int kNumIterations = 50; 49eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 50eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman for (int i = 0; i < kNumIterations; ++i) { 51eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman auto s0 = make_surface(ctx); 52bcf65edf2ca14bfd63712f7fb6a347973213daf5Brian Osman if (!s0) { 53bcf65edf2ca14bfd63712f7fb6a347973213daf5Brian Osman // MSAA may not be supported 54bcf65edf2ca14bfd63712f7fb6a347973213daf5Brian Osman return; 55bcf65edf2ca14bfd63712f7fb6a347973213daf5Brian Osman } 56eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 57eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman auto s1 = make_surface(ctx); 58eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s1->getCanvas()->clear(SK_ColorBLACK); 59eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s1->getCanvas()->drawOval(rect, paint); 60eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkBitmap b1 = read_pixels(s1); 61eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s1 = nullptr; 62eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 63eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // The bug requires that all three of the following surfaces are cleared to the same color 64eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman auto s2 = make_surface(ctx); 65eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s2->getCanvas()->clear(SK_ColorBLUE); 66eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkBitmap b2 = read_pixels(s2); 67eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s2 = nullptr; 68eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 69eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman auto s3 = make_surface(ctx); 70eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s3->getCanvas()->clear(SK_ColorBLUE); 71eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkBitmap b3 = read_pixels(s3); 72eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s0->getCanvas()->drawBitmap(b3, 0, 0); 73eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s3 = nullptr; 74eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 75eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman auto s4 = make_surface(ctx); 76eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s4->getCanvas()->clear(SK_ColorBLUE); 77eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman s4->getCanvas()->drawOval(rect, paint); 78eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 79eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // When this fails, b4 will "succeed", but return an empty bitmap (containing just the 80eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // clear color). Regardless, b5 will contain the oval that was just drawn, so diffing the 81eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman // two bitmaps tests for the failure case. 82eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkBitmap b4 = read_pixels(s4); 83eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman SkBitmap b5 = read_pixels(s4); 84eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 85eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman bool match = true; 86eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman for (int y = 0; y < b4.height() && match; ++y) { 87eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman for (int x = 0; x < b4.width() && match; ++x) { 88eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman uint32_t pixelA = *b4.getAddr32(x, y); 89eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman uint32_t pixelB = *b5.getAddr32(x, y); 90eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman if (pixelA != pixelB) { 91eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman match = false; 92eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman } 93eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman } 94eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman } 95eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 96eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman REPORTER_ASSERT(reporter, match); 97eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman } 98eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman} 99eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman 100eee3c09e96d0a925e1ecaec118cc3ac0294e86eaBrian Osman#endif 101