diff options
Diffstat (limited to 'minui')
-rw-r--r-- | minui/graphics_adf.cpp | 89 | ||||
-rw-r--r-- | minui/graphics_adf.h | 32 | ||||
-rw-r--r-- | minui/graphics_drm.cpp | 10 | ||||
-rw-r--r-- | minui/graphics_drm.h | 7 | ||||
-rw-r--r-- | minui/graphics_fbdev.cpp | 81 | ||||
-rw-r--r-- | minui/graphics_fbdev.h | 31 | ||||
-rw-r--r-- | minui/include/minui/minui.h | 22 | ||||
-rw-r--r-- | minui/resources.cpp | 147 |
8 files changed, 210 insertions, 209 deletions
diff --git a/minui/graphics_adf.cpp b/minui/graphics_adf.cpp index 6fc193f74..9eea497d6 100644 --- a/minui/graphics_adf.cpp +++ b/minui/graphics_adf.cpp @@ -20,6 +20,7 @@ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/mman.h> #include <unistd.h> @@ -28,51 +29,60 @@ #include "minui/minui.h" -MinuiBackendAdf::MinuiBackendAdf() - : intf_fd(-1), dev(), current_surface(0), n_surfaces(0), surfaces() {} +GRSurfaceAdf::~GRSurfaceAdf() { + if (mmapped_buffer_) { + munmap(mmapped_buffer_, pitch * height); + } + if (fence_fd != -1) { + close(fence_fd); + } + if (fd != -1) { + close(fd); + } +} -int MinuiBackendAdf::SurfaceInit(const drm_mode_modeinfo* mode, GRSurfaceAdf* surf) { - *surf = {}; - surf->fence_fd = -1; - surf->fd = adf_interface_simple_buffer_alloc(intf_fd, mode->hdisplay, mode->vdisplay, format, - &surf->offset, &surf->pitch); - if (surf->fd < 0) { - return surf->fd; +std::unique_ptr<GRSurfaceAdf> GRSurfaceAdf::Create(int intf_fd, const drm_mode_modeinfo* mode, + __u32 format, int* err) { + __u32 offset; + __u32 pitch; + auto fd = adf_interface_simple_buffer_alloc(intf_fd, mode->hdisplay, mode->vdisplay, format, + &offset, &pitch); + + if (fd < 0) { + *err = fd; + return nullptr; } - surf->width = mode->hdisplay; - surf->height = mode->vdisplay; - surf->row_bytes = surf->pitch; - surf->pixel_bytes = (format == DRM_FORMAT_RGB565) ? 2 : 4; + std::unique_ptr<GRSurfaceAdf> surf = std::unique_ptr<GRSurfaceAdf>( + new GRSurfaceAdf(mode->hdisplay, mode->vdisplay, pitch, (format == DRM_FORMAT_RGB565 ? 2 : 4), + offset, pitch, fd)); 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; + *err = -errno; + return nullptr; } surf->mmapped_buffer_ = static_cast<uint8_t*>(mmapped); - return 0; + return surf; } +MinuiBackendAdf::MinuiBackendAdf() : intf_fd(-1), dev(), current_surface(0), n_surfaces(0) {} + int MinuiBackendAdf::InterfaceInit() { adf_interface_data intf_data; - int err = adf_get_interface_data(intf_fd, &intf_data); - if (err < 0) return err; + if (int err = adf_get_interface_data(intf_fd, &intf_data); err < 0) return err; - int ret = 0; - err = SurfaceInit(&intf_data.current_mode, &surfaces[0]); - if (err < 0) { - fprintf(stderr, "allocating surface 0 failed: %s\n", strerror(-err)); - ret = err; + int result = 0; + surfaces[0] = GRSurfaceAdf::Create(intf_fd, &intf_data.current_mode, format, &result); + if (!surfaces[0]) { + fprintf(stderr, "Failed to allocate surface 0: %s\n", strerror(-result)); goto done; } - err = SurfaceInit(&intf_data.current_mode, &surfaces[1]); - if (err < 0) { - fprintf(stderr, "allocating surface 1 failed: %s\n", strerror(-err)); - surfaces[1] = {}; + surfaces[1] = GRSurfaceAdf::Create(intf_fd, &intf_data.current_mode, format, &result); + if (!surfaces[1]) { + fprintf(stderr, "Failed to allocate surface 1: %s\n", strerror(-result)); n_surfaces = 1; } else { n_surfaces = 2; @@ -80,7 +90,7 @@ int MinuiBackendAdf::InterfaceInit() { done: adf_free_interface_data(&intf_data); - return ret; + return result; } int MinuiBackendAdf::DeviceInit(adf_device* dev) { @@ -153,12 +163,12 @@ GRSurface* MinuiBackendAdf::Init() { } void MinuiBackendAdf::Sync(GRSurfaceAdf* surf) { - static constexpr unsigned int warningTimeout = 3000; + static constexpr unsigned int kWarningTimeout = 3000; if (surf == nullptr) return; if (surf->fence_fd >= 0) { - int err = sync_wait(surf->fence_fd, warningTimeout); + int err = sync_wait(surf->fence_fd, kWarningTimeout); if (err < 0) { perror("adf sync fence wait error\n"); } @@ -169,33 +179,22 @@ void MinuiBackendAdf::Sync(GRSurfaceAdf* surf) { } GRSurface* MinuiBackendAdf::Flip() { - GRSurfaceAdf* surf = &surfaces[current_surface]; + const auto& surf = surfaces[current_surface]; int fence_fd = adf_interface_simple_post(intf_fd, eng_id, surf->width, surf->height, format, surf->fd, surf->offset, surf->pitch, -1); if (fence_fd >= 0) surf->fence_fd = fence_fd; current_surface = (current_surface + 1) % n_surfaces; - Sync(&surfaces[current_surface]); - return &surfaces[current_surface]; + Sync(surfaces[current_surface].get()); + return surfaces[current_surface].get(); } void MinuiBackendAdf::Blank(bool blank) { adf_interface_blank(intf_fd, blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON); } -void MinuiBackendAdf::SurfaceDestroy(GRSurfaceAdf* surf) { - if (surf->mmapped_buffer_) { - munmap(surf->mmapped_buffer_, surf->pitch * surf->height); - } - close(surf->fence_fd); - close(surf->fd); -} - MinuiBackendAdf::~MinuiBackendAdf() { adf_device_close(&dev); - for (unsigned int i = 0; i < n_surfaces; i++) { - SurfaceDestroy(&surfaces[i]); - } if (intf_fd >= 0) close(intf_fd); } diff --git a/minui/graphics_adf.h b/minui/graphics_adf.h index 099d32962..bf9842878 100644 --- a/minui/graphics_adf.h +++ b/minui/graphics_adf.h @@ -17,6 +17,9 @@ #pragma once #include <stdint.h> +#include <sys/types.h> + +#include <memory> #include <adf/adf.h> @@ -25,6 +28,11 @@ class GRSurfaceAdf : public GRSurface { public: + ~GRSurfaceAdf() override; + + static std::unique_ptr<GRSurfaceAdf> Create(int intf_fd, const drm_mode_modeinfo* mode, + __u32 format, int* err); + uint8_t* data() override { return mmapped_buffer_; } @@ -32,34 +40,36 @@ class GRSurfaceAdf : public GRSurface { private: friend class MinuiBackendAdf; - int fence_fd; - int fd; - __u32 offset; - __u32 pitch; + GRSurfaceAdf(int width, int height, int row_bytes, int pixel_bytes, __u32 offset, __u32 pitch, + int fd) + : GRSurface(width, height, row_bytes, pixel_bytes), offset(offset), pitch(pitch), fd(fd) {} + + const __u32 offset; + const __u32 pitch; + int fd; + int fence_fd{ -1 }; uint8_t* mmapped_buffer_{ nullptr }; }; class MinuiBackendAdf : public MinuiBackend { public: + MinuiBackendAdf(); + ~MinuiBackendAdf() override; GRSurface* Init() override; GRSurface* Flip() override; void Blank(bool) override; - ~MinuiBackendAdf() override; - MinuiBackendAdf(); private: - int SurfaceInit(const drm_mode_modeinfo* mode, GRSurfaceAdf* surf); int InterfaceInit(); int DeviceInit(adf_device* dev); - void SurfaceDestroy(GRSurfaceAdf* surf); void Sync(GRSurfaceAdf* surf); int intf_fd; adf_id_t eng_id; __u32 format; adf_device dev; - unsigned int current_surface; - unsigned int n_surfaces; - GRSurfaceAdf surfaces[2]; + size_t current_surface; + size_t n_surfaces; + std::unique_ptr<GRSurfaceAdf> surfaces[2]; }; diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp index f81fd9d5c..765e2625a 100644 --- a/minui/graphics_drm.cpp +++ b/minui/graphics_drm.cpp @@ -102,15 +102,15 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he return nullptr; } - std::unique_ptr<GRSurfaceDrm> surface = std::make_unique<GRSurfaceDrm>(drm_fd); - surface->handle = create_dumb.handle; + // Cannot use std::make_unique to access non-public ctor. + auto surface = std::unique_ptr<GRSurfaceDrm>(new GRSurfaceDrm( + width, height, create_dumb.pitch, create_dumb.bpp / 8, drm_fd, create_dumb.handle)); uint32_t handles[4], pitches[4], offsets[4]; handles[0] = surface->handle; pitches[0] = create_dumb.pitch; offsets[0] = 0; - if (drmModeAddFB2(drm_fd, width, height, format, handles, pitches, offsets, &surface->fb_id, 0) != 0) { perror("Failed to drmModeAddFB2"); @@ -124,10 +124,6 @@ std::unique_ptr<GRSurfaceDrm> GRSurfaceDrm::Create(int drm_fd, int width, int he return nullptr; } - surface->height = height; - surface->width = width; - surface->row_bytes = create_dumb.pitch; - surface->pixel_bytes = create_dumb.bpp / 8; auto mmapped = mmap(nullptr, surface->height * surface->row_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd, map_dumb.offset); if (mmapped == MAP_FAILED) { diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h index 02db89f05..6ba46e60b 100644 --- a/minui/graphics_drm.h +++ b/minui/graphics_drm.h @@ -20,7 +20,6 @@ #include <memory> -#include <android-base/macros.h> #include <xf86drmMode.h> #include "graphics.h" @@ -28,7 +27,6 @@ class GRSurfaceDrm : public GRSurface { public: - explicit GRSurfaceDrm(int drm_fd) : drm_fd_(drm_fd) {} ~GRSurfaceDrm() override; // Creates a GRSurfaceDrm instance. @@ -41,13 +39,14 @@ class GRSurfaceDrm : public GRSurface { private: friend class MinuiBackendDrm; + GRSurfaceDrm(int width, int height, int row_bytes, int pixel_bytes, int drm_fd, uint32_t handle) + : GRSurface(width, height, row_bytes, pixel_bytes), drm_fd_(drm_fd), handle(handle) {} + const int drm_fd_; uint32_t fb_id{ 0 }; uint32_t handle{ 0 }; uint8_t* mmapped_buffer_{ nullptr }; - - DISALLOW_COPY_AND_ASSIGN(GRSurfaceDrm); }; class MinuiBackendDrm : public MinuiBackend { diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp index f958d62d4..93e4420d3 100644 --- a/minui/graphics_fbdev.cpp +++ b/minui/graphics_fbdev.cpp @@ -26,21 +26,29 @@ #include <sys/types.h> #include <unistd.h> +#include <memory> + +#include <android-base/unique_fd.h> + #include "minui/minui.h" -MinuiBackendFbdev::MinuiBackendFbdev() : gr_draw(nullptr), fb_fd(-1) {} +std::unique_ptr<GRSurfaceFbdev> GRSurfaceFbdev::Create(int width, int height, int row_bytes, + int pixel_bytes) { + // Cannot use std::make_unique to access non-public ctor. + return std::unique_ptr<GRSurfaceFbdev>(new GRSurfaceFbdev(width, height, row_bytes, pixel_bytes)); +} void MinuiBackendFbdev::Blank(bool blank) { int ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK); if (ret < 0) perror("ioctl(): blank"); } -void MinuiBackendFbdev::SetDisplayedFramebuffer(unsigned n) { +void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) { if (n > 1 || !double_buffered) return; - vi.yres_virtual = gr_framebuffer[0].height * 2; - vi.yoffset = n * gr_framebuffer[0].height; - vi.bits_per_pixel = gr_framebuffer[0].pixel_bytes * 8; + vi.yres_virtual = gr_framebuffer[0]->height * 2; + vi.yoffset = n * gr_framebuffer[0]->height; + vi.bits_per_pixel = gr_framebuffer[0]->pixel_bytes * 8; if (ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vi) < 0) { perror("active fb swap failed"); } @@ -48,7 +56,7 @@ void MinuiBackendFbdev::SetDisplayedFramebuffer(unsigned n) { } GRSurface* MinuiBackendFbdev::Init() { - int fd = open("/dev/graphics/fb0", O_RDWR); + android::base::unique_fd fd(open("/dev/graphics/fb0", O_RDWR)); if (fd == -1) { perror("cannot open fb0"); return nullptr; @@ -57,13 +65,11 @@ GRSurface* MinuiBackendFbdev::Init() { fb_fix_screeninfo fi; if (ioctl(fd, FBIOGET_FSCREENINFO, &fi) < 0) { perror("failed to get fb0 info"); - close(fd); return nullptr; } if (ioctl(fd, FBIOGET_VSCREENINFO, &vi) < 0) { perror("failed to get fb0 info"); - close(fd); return nullptr; } @@ -90,46 +96,41 @@ GRSurface* MinuiBackendFbdev::Init() { void* bits = mmap(0, fi.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (bits == MAP_FAILED) { perror("failed to mmap framebuffer"); - close(fd); return nullptr; } memset(bits, 0, fi.smem_len); - gr_framebuffer[0].width = vi.xres; - gr_framebuffer[0].height = vi.yres; - gr_framebuffer[0].row_bytes = fi.line_length; - gr_framebuffer[0].pixel_bytes = vi.bits_per_pixel / 8; - gr_framebuffer[0].buffer_ = static_cast<uint8_t*>(bits); - memset(gr_framebuffer[0].buffer_, 0, gr_framebuffer[0].height * gr_framebuffer[0].row_bytes); + gr_framebuffer[0] = + GRSurfaceFbdev::Create(vi.xres, vi.yres, fi.line_length, vi.bits_per_pixel / 8); + gr_framebuffer[0]->buffer_ = static_cast<uint8_t*>(bits); + memset(gr_framebuffer[0]->buffer_, 0, gr_framebuffer[0]->height * gr_framebuffer[0]->row_bytes); + + gr_framebuffer[1] = + GRSurfaceFbdev::Create(gr_framebuffer[0]->width, gr_framebuffer[0]->height, + gr_framebuffer[0]->row_bytes, gr_framebuffer[0]->pixel_bytes); /* check if we can use double buffering */ if (vi.yres * fi.line_length * 2 <= fi.smem_len) { double_buffered = true; - gr_framebuffer[1] = gr_framebuffer[0]; - gr_framebuffer[1].buffer_ = - gr_framebuffer[0].buffer_ + gr_framebuffer[0].height * gr_framebuffer[0].row_bytes; - - gr_draw = gr_framebuffer + 1; - + gr_framebuffer[1]->buffer_ = + gr_framebuffer[0]->buffer_ + gr_framebuffer[0]->height * gr_framebuffer[0]->row_bytes; } else { double_buffered = false; - // Without double-buffering, we allocate RAM for a buffer to - // draw in, and then "flipping" the buffer consists of a - // memcpy from the buffer we allocated to the framebuffer. - - gr_draw = new GRSurfaceFbdev; - *gr_draw = gr_framebuffer[0]; - gr_draw->buffer_ = new uint8_t[gr_draw->height * gr_draw->row_bytes]; + // Without double-buffering, we allocate RAM for a buffer to draw in, and then "flipping" the + // buffer consists of a memcpy from the buffer we allocated to the framebuffer. + memory_buffer.resize(gr_framebuffer[1]->height * gr_framebuffer[1]->row_bytes); + gr_framebuffer[1]->buffer_ = memory_buffer.data(); } + gr_draw = gr_framebuffer[1].get(); memset(gr_draw->buffer_, 0, gr_draw->height * gr_draw->row_bytes); - fb_fd = fd; + fb_fd = std::move(fd); SetDisplayedFramebuffer(0); - printf("framebuffer: %d (%d x %d)\n", fb_fd, gr_draw->width, gr_draw->height); + printf("framebuffer: %d (%d x %d)\n", fb_fd.get(), gr_draw->width, gr_draw->height); Blank(true); Blank(false); @@ -139,25 +140,13 @@ GRSurface* MinuiBackendFbdev::Init() { GRSurface* MinuiBackendFbdev::Flip() { if (double_buffered) { - // Change gr_draw to point to the buffer currently displayed, - // then flip the driver so we're displaying the other buffer - // instead. - gr_draw = gr_framebuffer + displayed_buffer; + // Change gr_draw to point to the buffer currently displayed, then flip the driver so we're + // displaying the other buffer instead. + gr_draw = gr_framebuffer[displayed_buffer].get(); SetDisplayedFramebuffer(1 - displayed_buffer); } else { // Copy from the in-memory surface to the framebuffer. - memcpy(gr_framebuffer[0].buffer_, gr_draw->buffer_, gr_draw->height * gr_draw->row_bytes); + memcpy(gr_framebuffer[0]->buffer_, gr_draw->buffer_, gr_draw->height * gr_draw->row_bytes); } return gr_draw; } - -MinuiBackendFbdev::~MinuiBackendFbdev() { - close(fb_fd); - fb_fd = -1; - - if (!double_buffered && gr_draw) { - delete[] gr_draw->buffer_; - delete gr_draw; - } - gr_draw = nullptr; -} diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h index be813dccb..016ab88bc 100644 --- a/minui/graphics_fbdev.h +++ b/minui/graphics_fbdev.h @@ -19,37 +19,52 @@ #include <linux/fb.h> #include <stdint.h> +#include <memory> +#include <vector> + +#include <android-base/unique_fd.h> + #include "graphics.h" #include "minui/minui.h" class GRSurfaceFbdev : public GRSurface { public: + // Creates and returns a GRSurfaceFbdev instance, or nullptr on error. + static std::unique_ptr<GRSurfaceFbdev> Create(int width, int height, int row_bytes, + int pixel_bytes); + uint8_t* data() override { return buffer_; } + protected: + using GRSurface::GRSurface; + private: friend class MinuiBackendFbdev; // Points to the start of the buffer: either the mmap'd framebuffer or one allocated in-memory. - uint8_t* buffer_; + uint8_t* buffer_{ nullptr }; }; class MinuiBackendFbdev : public MinuiBackend { public: + MinuiBackendFbdev() = default; + ~MinuiBackendFbdev() override = default; + GRSurface* Init() override; GRSurface* Flip() override; void Blank(bool) override; - ~MinuiBackendFbdev() override; - MinuiBackendFbdev(); private: - void SetDisplayedFramebuffer(unsigned n); + void SetDisplayedFramebuffer(size_t n); - GRSurfaceFbdev gr_framebuffer[2]; + std::unique_ptr<GRSurfaceFbdev> gr_framebuffer[2]; + // Points to the current surface (i.e. one of the two gr_framebuffer's). + GRSurfaceFbdev* gr_draw{ nullptr }; bool double_buffered; - GRSurfaceFbdev* gr_draw; - int displayed_buffer; + std::vector<uint8_t> memory_buffer; + size_t displayed_buffer{ 0 }; fb_var_screeninfo vi; - int fb_fd; + android::base::unique_fd fb_fd; }; diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h index e9bd1c4f1..0b499e621 100644 --- a/minui/include/minui/minui.h +++ b/minui/include/minui/minui.h @@ -24,19 +24,24 @@ #include <string> #include <vector> +#include <android-base/macros.h> + // // Graphics. // class GRSurface { public: - GRSurface() = default; virtual ~GRSurface(); - // Creates and returns a GRSurface instance for the given data_size. The starting address of the - // surface data is aligned to SURFACE_DATA_ALIGNMENT. Returns the created GRSurface instance (in - // std::unique_ptr), or nullptr on error. - static std::unique_ptr<GRSurface> Create(size_t data_size); + // Creates and returns a GRSurface instance that's sufficient for storing an image of the given + // size. The starting address of the surface data is aligned to SURFACE_DATA_ALIGNMENT. Returns + // the created GRSurface instance (in std::unique_ptr), or nullptr on error. + static std::unique_ptr<GRSurface> Create(int width, int height, int row_bytes, int pixel_bytes, + size_t data_size); + + // Clones the current GRSurface instance (i.e. an image). + std::unique_ptr<GRSurface> Clone() const; virtual uint8_t* data() { return data_; @@ -51,8 +56,15 @@ class GRSurface { int row_bytes; int pixel_bytes; + protected: + GRSurface(int width, int height, int row_bytes, int pixel_bytes) + : width(width), height(height), row_bytes(row_bytes), pixel_bytes(pixel_bytes) {} + private: uint8_t* data_{ nullptr }; + size_t data_size_; + + DISALLOW_COPY_AND_ASSIGN(GRSurface); }; struct GRFont { diff --git a/minui/resources.cpp b/minui/resources.cpp index c01c1868e..9027bc668 100644 --- a/minui/resources.cpp +++ b/minui/resources.cpp @@ -39,16 +39,24 @@ static std::string g_resource_dir{ "/res/images" }; -std::unique_ptr<GRSurface> GRSurface::Create(size_t data_size) { +std::unique_ptr<GRSurface> GRSurface::Create(int width, int height, int row_bytes, int pixel_bytes, + size_t data_size) { static constexpr size_t kSurfaceDataAlignment = 8; - std::unique_ptr<GRSurface> result = std::make_unique<GRSurface>(); - size_t aligned_size = + // Cannot use std::make_unique to access non-public ctor. + auto result = std::unique_ptr<GRSurface>(new GRSurface(width, height, row_bytes, pixel_bytes)); + result->data_size_ = (data_size + kSurfaceDataAlignment - 1) / kSurfaceDataAlignment * kSurfaceDataAlignment; - result->data_ = static_cast<uint8_t*>(aligned_alloc(kSurfaceDataAlignment, aligned_size)); + result->data_ = static_cast<uint8_t*>(aligned_alloc(kSurfaceDataAlignment, result->data_size_)); if (result->data_ == nullptr) return nullptr; return result; } +std::unique_ptr<GRSurface> GRSurface::Clone() const { + auto result = GRSurface::Create(width, height, row_bytes, pixel_bytes, data_size_); + memcpy(result->data_, data_, data_size_); + return result; +} + GRSurface::~GRSurface() { if (data_ != nullptr) { free(data_); @@ -68,7 +76,7 @@ PngHandler::PngHandler(const std::string& name) { return; } - unsigned char header[8]; + uint8_t header[8]; size_t bytesRead = fread(header, 1, sizeof(header), png_fp_.get()); if (bytesRead != sizeof(header)) { error_code_ = -2; @@ -131,70 +139,49 @@ PngHandler::~PngHandler() { } } -// "display" surfaces are transformed into the framebuffer's required -// pixel format (currently only RGBX is supported) at load time, so -// gr_blit() can be nothing more than a memcpy() for each row. The -// next two functions are the only ones that know anything about the -// framebuffer pixel format; they need to be modified if the -// framebuffer format changes (but nothing else should). - -// Allocates and returns a GRSurface* sufficient for storing an image of the indicated size in the -// framebuffer pixel format. -static std::unique_ptr<GRSurface> init_display_surface(png_uint_32 width, png_uint_32 height) { - std::unique_ptr<GRSurface> surface = GRSurface::Create(width * height * 4); - if (!surface) return nullptr; - - surface->width = width; - surface->height = height; - surface->row_bytes = width * 4; - surface->pixel_bytes = 4; - - return surface; -} +// "display" surfaces are transformed into the framebuffer's required pixel format (currently only +// RGBX is supported) at load time, so gr_blit() can be nothing more than a memcpy() for each row. -// Copy 'input_row' to 'output_row', transforming it to the -// framebuffer pixel format. The input format depends on the value of -// 'channels': +// Copies 'input_row' to 'output_row', transforming it to the framebuffer pixel format. The input +// format depends on the value of 'channels': // // 1 - input is 8-bit grayscale // 3 - input is 24-bit RGB // 4 - input is 32-bit RGBA/RGBX // // 'width' is the number of pixels in the row. -static void transform_rgb_to_draw(unsigned char* input_row, - unsigned char* output_row, - int channels, int width) { - int x; - unsigned char* ip = input_row; - unsigned char* op = output_row; - - switch (channels) { - case 1: - // expand gray level to RGBX - for (x = 0; x < width; ++x) { - *op++ = *ip; - *op++ = *ip; - *op++ = *ip; - *op++ = 0xff; - ip++; - } - break; - - case 3: - // expand RGBA to RGBX - for (x = 0; x < width; ++x) { - *op++ = *ip++; - *op++ = *ip++; - *op++ = *ip++; - *op++ = 0xff; - } - break; - - case 4: - // copy RGBA to RGBX - memcpy(output_row, input_row, width*4); - break; - } +static void TransformRgbToDraw(const uint8_t* input_row, uint8_t* output_row, int channels, + int width) { + const uint8_t* ip = input_row; + uint8_t* op = output_row; + + switch (channels) { + case 1: + // expand gray level to RGBX + for (int x = 0; x < width; ++x) { + *op++ = *ip; + *op++ = *ip; + *op++ = *ip; + *op++ = 0xff; + ip++; + } + break; + + case 3: + // expand RGBA to RGBX + for (int x = 0; x < width; ++x) { + *op++ = *ip++; + *op++ = *ip++; + *op++ = *ip++; + *op++ = 0xff; + } + break; + + case 4: + // copy RGBA to RGBX + memcpy(output_row, input_row, width * 4); + break; + } } int res_create_display_surface(const char* name, GRSurface** pSurface) { @@ -207,7 +194,7 @@ int res_create_display_surface(const char* name, GRSurface** pSurface) { png_uint_32 width = png_handler.width(); png_uint_32 height = png_handler.height(); - std::unique_ptr<GRSurface> surface = init_display_surface(width, height); + auto surface = GRSurface::Create(width, height, width * 4, 4, width * height * 4); if (!surface) { return -8; } @@ -218,10 +205,10 @@ int res_create_display_surface(const char* name, GRSurface** pSurface) { } for (png_uint_32 y = 0; y < height; ++y) { - std::vector<unsigned char> p_row(width * 4); + std::vector<uint8_t> p_row(width * 4); png_read_row(png_ptr, p_row.data(), nullptr); - transform_rgb_to_draw(p_row.data(), surface->data() + y * surface->row_bytes, - png_handler.channels(), width); + TransformRgbToDraw(p_row.data(), surface->data() + y * surface->row_bytes, + png_handler.channels(), width); } *pSurface = surface.release(); @@ -277,7 +264,9 @@ int res_create_multi_display_surface(const char* name, int* frames, int* fps, goto exit; } for (int i = 0; i < *frames; ++i) { - auto created_surface = init_display_surface(width, height / *frames); + auto height_per_frame = height / *frames; + auto created_surface = + GRSurface::Create(width, height_per_frame, width * 4, 4, width * height_per_frame); if (!created_surface) { result = -8; goto exit; @@ -290,11 +279,11 @@ int res_create_multi_display_surface(const char* name, int* frames, int* fps, } for (png_uint_32 y = 0; y < height; ++y) { - std::vector<unsigned char> p_row(width * 4); + std::vector<uint8_t> p_row(width * 4); png_read_row(png_ptr, p_row.data(), nullptr); int frame = y % *frames; - unsigned char* out_row = surface[frame]->data() + (y / *frames) * surface[frame]->row_bytes; - transform_rgb_to_draw(p_row.data(), out_row, png_handler.channels(), width); + uint8_t* out_row = surface[frame]->data() + (y / *frames) * surface[frame]->row_bytes; + TransformRgbToDraw(p_row.data(), out_row, png_handler.channels(), width); } *pSurface = surface; @@ -325,14 +314,10 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) { png_uint_32 width = png_handler.width(); png_uint_32 height = png_handler.height(); - std::unique_ptr<GRSurface> surface = GRSurface::Create(width * height); + auto surface = GRSurface::Create(width, height, width, 1, width * height); if (!surface) { return -8; } - surface->width = width; - surface->height = height; - surface->row_bytes = width; - surface->pixel_bytes = 1; PixelFormat pixel_format = gr_pixel_format(); if (pixel_format == PixelFormat::ABGR || pixel_format == PixelFormat::BGRA) { @@ -340,7 +325,7 @@ int res_create_alpha_surface(const char* name, GRSurface** pSurface) { } for (png_uint_32 y = 0; y < height; ++y) { - unsigned char* p_row = surface->data() + y * surface->row_bytes; + uint8_t* p_row = surface->data() + y * surface->row_bytes; png_read_row(png_ptr, p_row, nullptr); } @@ -389,7 +374,7 @@ std::vector<std::string> get_locales_in_png(const std::string& png_name) { } std::vector<std::string> result; - std::vector<unsigned char> row(png_handler.width()); + std::vector<uint8_t> row(png_handler.width()); for (png_uint_32 y = 0; y < png_handler.height(); ++y) { png_read_row(png_handler.png_ptr(), row.data(), nullptr); int h = (row[3] << 8) | row[2]; @@ -425,7 +410,7 @@ int res_create_localized_alpha_surface(const char* name, png_uint_32 height = png_handler.height(); for (png_uint_32 y = 0; y < height; ++y) { - std::vector<unsigned char> row(width); + std::vector<uint8_t> row(width); png_read_row(png_ptr, row.data(), nullptr); int w = (row[1] << 8) | row[0]; int h = (row[3] << 8) | row[2]; @@ -435,14 +420,10 @@ int res_create_localized_alpha_surface(const char* name, if (y + 1 + h >= height || matches_locale(loc, locale)) { printf(" %20s: %s (%d x %d @ %d)\n", name, loc, w, h, y); - std::unique_ptr<GRSurface> surface = GRSurface::Create(w * h); + auto surface = GRSurface::Create(w, h, w, 1, w * h); if (!surface) { return -8; } - surface->width = w; - surface->height = h; - surface->row_bytes = w; - surface->pixel_bytes = 1; for (int i = 0; i < h; ++i, ++y) { png_read_row(png_ptr, row.data(), nullptr); |