summaryrefslogtreecommitdiffstats
path: root/minui
diff options
context:
space:
mode:
Diffstat (limited to 'minui')
-rw-r--r--minui/graphics_adf.cpp89
-rw-r--r--minui/graphics_adf.h32
-rw-r--r--minui/graphics_drm.cpp10
-rw-r--r--minui/graphics_drm.h7
-rw-r--r--minui/graphics_fbdev.cpp81
-rw-r--r--minui/graphics_fbdev.h31
-rw-r--r--minui/include/minui/minui.h22
-rw-r--r--minui/resources.cpp147
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);