Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92bdb5a3 authored by Tao Bao's avatar Tao Bao
Browse files

minui: Move GRSurface into a class.

This CL adds GRSurface::Create() and dtor for managing the allocated
memory in GRSurface class. It also adds GRSurface::data() that hides the
underlying implementation, with both of const and non-const overloads.
This allows `const GRSurface&` to be more useful - previously it only
ensured a const member variable of `data`, instead of a read-only buffer
it points to.

It also marks the parameters in gr_texticon() and gr_blit() as const, as
they're incoming source that shouldn't be altered. It corrects the type
of gr_draw, which is the sink to be painted on (an earlier attempt was
made in [1], but didn't get the full picture correctly).

[1] https://android-review.googlesource.com/c/platform/bootable/recovery/+/704757/

Test: mmma -j bootable/recovery
Test: recovery_unit_test on marlin
Test: Run graphics test on marlin (fbdev).
Test: Run graphics test on blueline (drm).
Change-Id: I7904df084cd6c08fa04a9da97d01b4b1a6e3a20c
parent 24ead567
Loading
Loading
Loading
Loading
+30 −29
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ static uint32_t gr_current = ~0;
static constexpr uint32_t alpha_mask = 0xff000000;

// gr_draw is owned by backends.
static const GRSurface* gr_draw = nullptr;
static GRSurface* gr_draw = nullptr;
static GRRotation rotation = GRRotation::NONE;
static PixelFormat pixel_format = PixelFormat::UNKNOWN;

@@ -121,28 +121,29 @@ static void incr_y(uint32_t** p, int row_pixels) {
}

// Returns pixel pointer at given coordinates with rotation adjustment.
static uint32_t* pixel_at(const GRSurface* surf, int x, int y, int row_pixels) {
static uint32_t* PixelAt(GRSurface* surface, int x, int y, int row_pixels) {
  switch (rotation) {
    case GRRotation::NONE:
      return reinterpret_cast<uint32_t*>(surf->data) + y * row_pixels + x;
      return reinterpret_cast<uint32_t*>(surface->data()) + y * row_pixels + x;
    case GRRotation::RIGHT:
      return reinterpret_cast<uint32_t*>(surf->data) + x * row_pixels + (surf->width - y);
      return reinterpret_cast<uint32_t*>(surface->data()) + x * row_pixels + (surface->width - y);
    case GRRotation::DOWN:
      return reinterpret_cast<uint32_t*>(surf->data) + (surf->height - 1 - y) * row_pixels +
             (surf->width - 1 - x);
      return reinterpret_cast<uint32_t*>(surface->data()) + (surface->height - 1 - y) * row_pixels +
             (surface->width - 1 - x);
    case GRRotation::LEFT:
      return reinterpret_cast<uint32_t*>(surf->data) + (surf->height - 1 - x) * row_pixels + y;
      return reinterpret_cast<uint32_t*>(surface->data()) + (surface->height - 1 - x) * row_pixels +
             y;
    default:
      printf("invalid rotation %d", static_cast<int>(rotation));
  }
  return nullptr;
}

static void text_blend(uint8_t* src_p, int src_row_bytes, uint32_t* dst_p, int dst_row_pixels,
static void TextBlend(const uint8_t* src_p, int src_row_bytes, uint32_t* dst_p, int dst_row_pixels,
                      int width, int height) {
  uint8_t alpha_current = static_cast<uint8_t>((alpha_mask & gr_current) >> 24);
  for (int j = 0; j < height; ++j) {
    uint8_t* sx = src_p;
    const uint8_t* sx = src_p;
    uint32_t* px = dst_p;
    for (int i = 0; i < width; ++i, incr_x(&px, dst_row_pixels)) {
      uint8_t a = *sx++;
@@ -176,18 +177,18 @@ void gr_text(const GRFont* font, int x, int y, const char* s, bool bold) {
    }

    int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
    uint8_t* src_p = font->texture->data + ((ch - ' ') * font->char_width) +
    const uint8_t* src_p = font->texture->data() + ((ch - ' ') * font->char_width) +
                           (bold ? font->char_height * font->texture->row_bytes : 0);
    uint32_t* dst_p = pixel_at(gr_draw, x, y, row_pixels);
    uint32_t* dst_p = PixelAt(gr_draw, x, y, row_pixels);

    text_blend(src_p, font->texture->row_bytes, dst_p, row_pixels, font->char_width,
    TextBlend(src_p, font->texture->row_bytes, dst_p, row_pixels, font->char_width,
              font->char_height);

    x += font->char_width;
  }
}

void gr_texticon(int x, int y, GRSurface* icon) {
void gr_texticon(int x, int y, const GRSurface* icon) {
  if (icon == nullptr) return;

  if (icon->pixel_bytes != 1) {
@@ -201,10 +202,9 @@ void gr_texticon(int x, int y, GRSurface* icon) {
  if (outside(x, y) || outside(x + icon->width - 1, y + icon->height - 1)) return;

  int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
  uint8_t* src_p = icon->data;
  uint32_t* dst_p = pixel_at(gr_draw, x, y, row_pixels);

  text_blend(src_p, icon->row_bytes, dst_p, row_pixels, icon->width, icon->height);
  const uint8_t* src_p = icon->data();
  uint32_t* dst_p = PixelAt(gr_draw, x, y, row_pixels);
  TextBlend(src_p, icon->row_bytes, dst_p, row_pixels, icon->width, icon->height);
}

void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
@@ -221,9 +221,9 @@ void gr_clear() {
      (gr_current & 0xff) == ((gr_current >> 16) & 0xff) &&
      (gr_current & 0xff) == ((gr_current >> 24) & 0xff) &&
      gr_draw->row_bytes == gr_draw->width * gr_draw->pixel_bytes) {
    memset(gr_draw->data, gr_current & 0xff, gr_draw->height * gr_draw->row_bytes);
    memset(gr_draw->data(), gr_current & 0xff, gr_draw->height * gr_draw->row_bytes);
  } else {
    uint32_t* px = reinterpret_cast<uint32_t*>(gr_draw->data);
    uint32_t* px = reinterpret_cast<uint32_t*>(gr_draw->data());
    int row_diff = gr_draw->row_bytes / gr_draw->pixel_bytes - gr_draw->width;
    for (int y = 0; y < gr_draw->height; ++y) {
      for (int x = 0; x < gr_draw->width; ++x) {
@@ -244,7 +244,7 @@ void gr_fill(int x1, int y1, int x2, int y2) {
  if (outside(x1, y1) || outside(x2 - 1, y2 - 1)) return;

  int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
  uint32_t* p = pixel_at(gr_draw, x1, y1, row_pixels);
  uint32_t* p = PixelAt(gr_draw, x1, y1, row_pixels);
  uint8_t alpha = static_cast<uint8_t>(((gr_current & alpha_mask) >> 24));
  if (alpha > 0) {
    for (int y = y1; y < y2; ++y) {
@@ -258,7 +258,7 @@ void gr_fill(int x1, int y1, int x2, int y2) {
  }
}

void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
void gr_blit(const GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
  if (source == nullptr) return;

  if (gr_draw->pixel_bytes != source->pixel_bytes) {
@@ -274,11 +274,12 @@ void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
  if (rotation != GRRotation::NONE) {
    int src_row_pixels = source->row_bytes / source->pixel_bytes;
    int row_pixels = gr_draw->row_bytes / gr_draw->pixel_bytes;
    uint32_t* src_py = reinterpret_cast<uint32_t*>(source->data) + sy * source->row_bytes / 4 + sx;
    uint32_t* dst_py = pixel_at(gr_draw, dx, dy, row_pixels);
    const uint32_t* src_py =
        reinterpret_cast<const uint32_t*>(source->data()) + sy * source->row_bytes / 4 + sx;
    uint32_t* dst_py = PixelAt(gr_draw, dx, dy, row_pixels);

    for (int y = 0; y < h; y += 1) {
      uint32_t* src_px = src_py;
      const uint32_t* src_px = src_py;
      uint32_t* dst_px = dst_py;
      for (int x = 0; x < w; x += 1) {
        *dst_px = *src_px++;
@@ -288,8 +289,8 @@ void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) {
      incr_y(&dst_py, row_pixels);
    }
  } else {
    unsigned char* src_p = source->data + sy * source->row_bytes + sx * source->pixel_bytes;
    unsigned char* dst_p = gr_draw->data + dy * gr_draw->row_bytes + dx * gr_draw->pixel_bytes;
    const uint8_t* src_p = source->data() + sy * source->row_bytes + sx * source->pixel_bytes;
    uint8_t* dst_p = gr_draw->data() + dy * gr_draw->row_bytes + dx * gr_draw->pixel_bytes;

    for (int i = 0; i < h; ++i) {
      memcpy(dst_p, src_p, w * source->pixel_bytes);
+7 −5
Original line number Diff line number Diff line
@@ -45,14 +45,14 @@ int MinuiBackendAdf::SurfaceInit(const drm_mode_modeinfo* mode, GRSurfaceAdf* su
  surf->row_bytes = surf->pitch;
  surf->pixel_bytes = (format == DRM_FORMAT_RGB565) ? 2 : 4;

  surf->data = static_cast<uint8_t*>(
      mmap(nullptr, surf->pitch * surf->height, PROT_WRITE, MAP_SHARED, surf->fd, surf->offset));
  if (surf->data == MAP_FAILED) {
  auto mmapped =
      mmap(nullptr, surf->pitch * surf->height, PROT_WRITE, MAP_SHARED, surf->fd, surf->offset);
  if (mmapped == MAP_FAILED) {
    int saved_errno = errno;
    close(surf->fd);
    return -saved_errno;
  }

  surf->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
  return 0;
}

@@ -185,7 +185,9 @@ void MinuiBackendAdf::Blank(bool blank) {
}

void MinuiBackendAdf::SurfaceDestroy(GRSurfaceAdf* surf) {
  munmap(surf->data, surf->pitch * surf->height);
  if (surf->mmapped_buffer_) {
    munmap(surf->mmapped_buffer_, surf->pitch * surf->height);
  }
  close(surf->fence_fd);
  close(surf->fd);
}
+12 −5
Original line number Diff line number Diff line
@@ -14,21 +14,30 @@
 * limitations under the License.
 */

#ifndef _GRAPHICS_ADF_H_
#define _GRAPHICS_ADF_H_
#pragma once

#include <stdint.h>

#include <adf/adf.h>

#include "graphics.h"
#include "minui/minui.h"

class GRSurfaceAdf : public GRSurface {
 public:
  uint8_t* data() override {
    return mmapped_buffer_;
  }

 private:
  friend class MinuiBackendAdf;

  int fence_fd;
  int fd;
  __u32 offset;
  __u32 pitch;

  friend class MinuiBackendAdf;
  uint8_t* mmapped_buffer_{ nullptr };
};

class MinuiBackendAdf : public MinuiBackend {
@@ -54,5 +63,3 @@ class MinuiBackendAdf : public MinuiBackend {
  unsigned int n_surfaces;
  GRSurfaceAdf surfaces[2];
};

#endif  // _GRAPHICS_ADF_H_
+6 −7
Original line number Diff line number Diff line
@@ -70,8 +70,8 @@ void MinuiBackendDrm::Blank(bool blank) {
void MinuiBackendDrm::DrmDestroySurface(GRSurfaceDrm* surface) {
  if (!surface) return;

  if (surface->data) {
    munmap(surface->data, surface->row_bytes * surface->height);
  if (surface->mmapped_buffer_) {
    munmap(surface->mmapped_buffer_, surface->row_bytes * surface->height);
  }

  if (surface->fb_id) {
@@ -172,15 +172,14 @@ GRSurfaceDrm* MinuiBackendDrm::DrmCreateSurface(int width, int height) {
  surface->width = width;
  surface->row_bytes = create_dumb.pitch;
  surface->pixel_bytes = create_dumb.bpp / 8;
  surface->data = static_cast<unsigned char*>(mmap(nullptr, surface->height * surface->row_bytes,
                                                   PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,
                                                   map_dumb.offset));
  if (surface->data == MAP_FAILED) {
  auto mmapped = mmap(nullptr, surface->height * surface->row_bytes, PROT_READ | PROT_WRITE,
                      MAP_SHARED, drm_fd, map_dumb.offset);
  if (mmapped == MAP_FAILED) {
    perror("mmap() failed");
    DrmDestroySurface(surface);
    return nullptr;
  }

  surface->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
  return surface;
}

+9 −6
Original line number Diff line number Diff line
@@ -14,8 +14,7 @@
 * limitations under the License.
 */

#ifndef _GRAPHICS_DRM_H_
#define _GRAPHICS_DRM_H_
#pragma once

#include <stdint.h>

@@ -25,11 +24,17 @@
#include "minui/minui.h"

class GRSurfaceDrm : public GRSurface {
 public:
  uint8_t* data() override {
    return mmapped_buffer_;
  }

 private:
  friend class MinuiBackendDrm;

  uint32_t fb_id;
  uint32_t handle;

  friend class MinuiBackendDrm;
  uint8_t* mmapped_buffer_{ nullptr };
};

class MinuiBackendDrm : public MinuiBackend {
@@ -54,5 +59,3 @@ class MinuiBackendDrm : public MinuiBackend {
  drmModeConnector* main_monitor_connector;
  int drm_fd;
};

#endif  // _GRAPHICS_DRM_H_
Loading