yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
metal_renderer.mm
Go to the documentation of this file.
2
3#if defined(__APPLE__)
4#include <TargetConditionals.h>
5#import <CoreFoundation/CoreFoundation.h>
6#endif
7
8#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1)
9#import <Metal/Metal.h>
10#import <MetalKit/MetalKit.h>
11#endif
12
13#include "app/gfx/core/bitmap.h"
15#include "util/log.h"
16#include "util/sdl_deleter.h"
17#include <algorithm>
18
19namespace yaze {
20namespace gfx {
21
25
26bool MetalRenderer::Initialize(SDL_Window* window) {
27 (void)window;
28#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1)
29 if (!metal_view_) {
30 LOG_WARN("MetalRenderer", "Metal view not attached");
31 return false;
32 }
33 auto* view = static_cast<MTKView*>(metal_view_);
34 id<MTLDevice> device = view.device;
35 if (!device) {
36 device = MTLCreateSystemDefaultDevice();
37 view.device = device;
38 }
39 if (!device) {
40 LOG_WARN("MetalRenderer", "Failed to create Metal device");
41 return false;
42 }
43 if (!command_queue_) {
44 id<MTLCommandQueue> queue = [device newCommandQueue];
45 command_queue_ = (__bridge_retained void*)queue;
46 }
47 return true;
48#else
49 return false;
50#endif
51}
52
54 if (command_queue_) {
55 CFRelease(command_queue_);
56 command_queue_ = nullptr;
57 }
58 render_target_ = nullptr;
59}
60
62#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1)
63 if (!metal_view_) {
64 return nullptr;
65 }
66
67 auto* view = static_cast<MTKView*>(metal_view_);
68 id<MTLDevice> device = view.device;
69 if (!device) {
70 device = MTLCreateSystemDefaultDevice();
71 view.device = device;
72 }
73 if (!device) {
74 return nullptr;
75 }
76
77 MTLTextureDescriptor* descriptor =
78 [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm
79 width:width
80 height:height
81 mipmapped:NO];
82 descriptor.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
83 descriptor.storageMode = MTLStorageModeShared;
84
85 id<MTLTexture> texture = [device newTextureWithDescriptor:descriptor];
86 return texture ? (__bridge_retained void*)texture : nullptr;
87#else
88 (void)width;
89 (void)height;
90 return nullptr;
91#endif
92}
93
95 uint32_t format,
96 int access) {
97 (void)format;
98 (void)access;
99 return CreateTexture(width, height);
100}
101
103#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1)
104 if (!texture) {
105 return;
106 }
107
108 SDL_Surface* surface = bitmap.surface();
109 if (!surface || !surface->pixels || surface->w <= 0 || surface->h <= 0) {
110 return;
111 }
112
113 auto converted_surface =
114 std::unique_ptr<SDL_Surface, util::SDL_Surface_Deleter>(
115 platform::ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA8888));
116 if (!converted_surface || !converted_surface->pixels) {
117 return;
118 }
119
120 id<MTLTexture> metal_texture = (__bridge id<MTLTexture>)texture;
121 MTLRegion region = {
122 {0, 0, 0},
123 {static_cast<NSUInteger>(converted_surface->w),
124 static_cast<NSUInteger>(converted_surface->h),
125 1}};
126 [metal_texture replaceRegion:region
127 mipmapLevel:0
128 withBytes:converted_surface->pixels
129 bytesPerRow:converted_surface->pitch];
130#else
131 (void)texture;
132 (void)bitmap;
133#endif
134}
135
137 if (!texture) {
138 return;
139 }
140 if (render_target_ == texture) {
141 render_target_ = nullptr;
142 }
143#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1)
144 CFRelease(texture);
145#else
146 (void)texture;
147#endif
148}
149
150bool MetalRenderer::LockTexture(TextureHandle texture, SDL_Rect* rect,
151 void** pixels, int* pitch) {
152 (void)texture;
153 (void)rect;
154 (void)pixels;
155 (void)pitch;
156 return false;
157}
158
160 (void)texture;
161}
162
165
168
169void MetalRenderer::RenderCopy(TextureHandle texture, const SDL_Rect* srcrect,
170 const SDL_Rect* dstrect) {
171#if defined(__APPLE__) && (TARGET_OS_IPHONE == 1 || TARGET_IPHONE_SIMULATOR == 1)
172 if (!texture || !render_target_ || !command_queue_) {
173 return;
174 }
175
176 id<MTLTexture> source = (__bridge id<MTLTexture>)texture;
177 id<MTLTexture> dest = (__bridge id<MTLTexture>)render_target_;
178
179 int src_x = srcrect ? srcrect->x : 0;
180 int src_y = srcrect ? srcrect->y : 0;
181 int src_w = srcrect ? srcrect->w : static_cast<int>(source.width);
182 int src_h = srcrect ? srcrect->h : static_cast<int>(source.height);
183
184 int dst_x = dstrect ? dstrect->x : 0;
185 int dst_y = dstrect ? dstrect->y : 0;
186
187 src_w = std::min(src_w, static_cast<int>(source.width) - src_x);
188 src_h = std::min(src_h, static_cast<int>(source.height) - src_y);
189
190 if (src_w <= 0 || src_h <= 0) {
191 return;
192 }
193
194 MTLOrigin src_origin = {static_cast<NSUInteger>(src_x),
195 static_cast<NSUInteger>(src_y),
196 0};
197 MTLSize src_size = {static_cast<NSUInteger>(src_w),
198 static_cast<NSUInteger>(src_h),
199 1};
200 MTLOrigin dst_origin = {static_cast<NSUInteger>(dst_x),
201 static_cast<NSUInteger>(dst_y),
202 0};
203
204 id<MTLCommandQueue> queue = (__bridge id<MTLCommandQueue>)command_queue_;
205 id<MTLCommandBuffer> command_buffer = [queue commandBuffer];
206 id<MTLBlitCommandEncoder> blit = [command_buffer blitCommandEncoder];
207 [blit copyFromTexture:source
208 sourceSlice:0
209 sourceLevel:0
210 sourceOrigin:src_origin
211 sourceSize:src_size
212 toTexture:dest
213 destinationSlice:0
214 destinationLevel:0
215 destinationOrigin:dst_origin];
216 [blit endEncoding];
217 [command_buffer commit];
218 [command_buffer waitUntilCompleted];
219#else
220 (void)texture;
221 (void)srcrect;
222 (void)dstrect;
223#endif
224}
225
229
230void MetalRenderer::SetDrawColor(SDL_Color color) {
231 (void)color;
232}
233
237
239 metal_view_ = view;
240}
241
242} // namespace gfx
243} // namespace yaze
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
SDL_Surface * surface() const
Definition bitmap.h:379
void RenderCopy(TextureHandle texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect) override
Copies a portion of a texture to the current render target.
void Shutdown() override
Shuts down the renderer and releases all associated resources.
TextureHandle CreateTexture(int width, int height) override
Creates a new, empty texture.
bool Initialize(SDL_Window *window) override
Initializes the renderer with a given window.
void SetMetalView(void *view)
void SetRenderTarget(TextureHandle texture) override
Sets the render target for subsequent drawing operations.
TextureHandle CreateTextureWithFormat(int width, int height, uint32_t format, int access) override
Creates a new texture with a specific pixel format.
void DestroyTexture(TextureHandle texture) override
Destroys a texture and frees its associated resources.
void UpdateTexture(TextureHandle texture, const Bitmap &bitmap) override
Updates a texture with the pixel data from a Bitmap.
void Present() override
Presents the back buffer to the screen, making the rendered content visible.
void UnlockTexture(TextureHandle texture) override
void * GetBackendRenderer() override
Provides an escape hatch to get the underlying, concrete renderer object.
void SetDrawColor(SDL_Color color) override
Sets the color used for drawing operations (e.g., Clear).
void Clear() override
Clears the entire render target with the current draw color.
bool LockTexture(TextureHandle texture, SDL_Rect *rect, void **pixels, int *pitch) override
#define LOG_WARN(category, format,...)
Definition log.h:107
void * TextureHandle
An abstract handle representing a texture.
Definition irenderer.h:27
SDL_Surface * ConvertSurfaceFormat(SDL_Surface *surface, uint32_t format, uint32_t flags=0)
Convert a surface to a specific pixel format.
Definition sdl_compat.h:361
SDL2/SDL3 compatibility layer.