mac: ditch the image rep shit and try switching to a draw commands system
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good

This commit is contained in:
IoI_xD 2026-04-14 15:52:11 -07:00
commit bfc6d8e9af
2 changed files with 122 additions and 175 deletions

View file

@ -10,6 +10,29 @@
#include <Mw/MachDep.h>
#include <Mw/TypeDefs.h>
typedef struct {
enum {
COCOA_DRAW_COMMAND_POLY = 0,
COCOA_DRAW_COMMAND_LINES,
COCOA_DRAW_COMMAND_PIXMAP,
} type;
union {
struct {
MwPoint* points;
int points_count;
MwLLColor color;
} poly;
struct {
MwPoint* points;
MwLLColor color;
} lines;
struct {
MwRect rect;
MwLLPixmap pixmap;
} pixmap;
};
} draw_command;
#ifdef __OBJC__
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@ -81,23 +104,13 @@
@end
@interface MilskoCocoaView : NSView {
MwBool _child;
@public
unsigned char* buf;
NSBitmapImageRep* rep;
NSGraphicsContext* context;
MwBool valid;
NSRect givenRect;
float x;
float y;
float width;
float height;
MwBool _child;
draw_command** commands;
}
- (void)initRepAndContextWithWidth:(float)w Height:(float)h;
- (NSGraphicsContext*)context;
- (void)destroy;
- (NSBitmapImageRep*)getRep;
- (void)setChild;
@end

View file

@ -80,106 +80,101 @@ static void recursive_dispatch_key_released(MwLL handle, int* k) {
@implementation MilskoCocoaView
- (id)initWithFrame:(NSRect)frame {
givenRect = frame;
x = frame.origin.x;
y = frame.origin.y;
width = frame.size.width;
height = frame.size.height;
self = [super initWithFrame:frame];
if(width == 0 || height == 0) {
self->rep = NULL;
self->context = NULL;
} else {
[self initRepAndContextWithWidth:width Height:height];
}
self->_child = MwFALSE;
[super initWithFrame:frame];
self->commands = NULL;
return self;
}
- (void)setChild {
self->_child = MwTRUE;
}
- (NSGraphicsContext*)context {
return self->context;
}
- (NSBitmapImageRep*)getRep {
return self->rep;
}
- (void)destroy {
arrfree(self->commands);
};
- (void)drawRect:(NSRect)dirtyRect {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSArray* subviews = [self subviews];
int i;
[super drawRect:dirtyRect];
if(!self->rep) {
if(dirtyRect.size.width && dirtyRect.size.height) {
[self initRepAndContextWithWidth:dirtyRect.size.width
Height:dirtyRect.size.height];
self->width = dirtyRect.size.width;
self->height = dirtyRect.size.height;
} else {
[pool release];
return;
for(i = 0; i < arrlen(self->commands); i++) {
draw_command* cmd = self->commands[i];
switch(cmd->type) {
case COCOA_DRAW_COMMAND_POLY: {
int i;
NSBezierPath* path = [NSBezierPath bezierPath];
NSColor* nscolor =
[NSColor colorWithCalibratedRed:cmd->poly.color->common.red / 255.
green:cmd->poly.color->common.green / 255.
blue:cmd->poly.color->common.blue / 255.
alpha:1.0];
[nscolor setFill];
for(i = 0; i < cmd->poly.points_count; i++) {
NSPoint p = localPointFlip(NSMakePoint(cmd->poly.points[i].x, cmd->poly.points[i].y), self);
if(i == 0) {
[path moveToPoint:p];
} else {
[path lineToPoint:p];
}
}
[path closePath];
[path fill];
free(cmd->poly.points);
MwLLFreeColor(cmd->poly.color);
free(cmd);
} break;
case COCOA_DRAW_COMMAND_LINES: {
int n;
NSBezierPath* path = [NSBezierPath bezierPath];
NSColor* nscolor =
[NSColor colorWithCalibratedRed:cmd->lines.color->common.red / 255.
green:cmd->lines.color->common.green / 255.
blue:cmd->lines.color->common.blue / 255.
alpha:1.0];
[nscolor setFill];
for(n = 0; n < 2; n++) {
NSPoint p = localPointFlip(NSMakePoint(cmd->lines.points[n].x, cmd->lines.points[n].y), self);
if(n == 0) {
[path moveToPoint:p];
} else {
[path lineToPoint:p];
}
}
[path closePath];
[path stroke];
free(cmd->lines.points);
MwLLFreeColor(cmd->lines.color);
free(cmd);
} break;
case COCOA_DRAW_COMMAND_PIXMAP: {
[cmd->pixmap.pixmap->cocoa.real.image
drawInRect:localRectFlip(NSMakeRect(cmd->pixmap.rect.x, cmd->pixmap.rect.y, cmd->pixmap.rect.width, cmd->pixmap.rect.height), self)
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0];
MwLLDestroyPixmap(cmd->pixmap.pixmap);
free(cmd);
} break;
}
}
[self->rep drawInRect:NSMakeRect(dirtyRect.origin.x, dirtyRect.origin.y, [self->rep pixelsWide], [self->rep pixelsHigh])];
arrfree(self->commands);
for(i = 0; i < [subviews count]; i++) {
MilskoCocoaView* subview = [subviews objectAtIndex:i];
NSRect bounds = [subview bounds];
[subview drawRect:bounds];
}
[pool release];
}
- (void)initRepAndContextWithWidth:(float)w Height:(float)h {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
self->buf = malloc(w * h * 4);
memset(self->buf, 255, w * h * 4);
self->rep =
[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:&self->buf
pixelsWide:w
pixelsHigh:h
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:w * 4
bitsPerPixel:32];
assert(self->rep);
[self->rep retain];
[self->rep setOpaque:MwFALSE];
[self->rep setAlpha:MwTRUE];
self->context =
[NSGraphicsContext graphicsContextWithBitmapImageRep:self->rep];
assert(self->context);
[self->context retain];
[pool release];
}
- (void)destroy {
[self->rep release];
[self->context release];
}
- (void)setFrameSize:(NSSize)newSize {
[super setFrameSize:newSize];
[self->rep setSize:newSize];
self->width = newSize.width;
self->height = newSize.height;
}
- (BOOL)canBecomeKeyView {
return YES;
}
@ -745,81 +740,31 @@ static void MwLLEndDrawImpl(MwLL handle) {
static void MwLLPolygonImpl(MwLL handle, MwPoint* points, int points_count,
MwLLColor color) {
MilskoCocoa* self = handle->cocoa.real;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSGraphicsContext* ctx = [self->view context];
if(ctx) {
int i;
NSBezierPath* path = [NSBezierPath bezierPath];
/* whatever rect we use for coordinate flipping */
NSRect _rect = self->parent ? [self->view bounds] : [self->window frame];
draw_command* poly = malloc(sizeof(draw_command));
poly->type = COCOA_DRAW_COMMAND_POLY;
NSColor* nscolor =
[NSColor colorWithCalibratedRed:color->common.red / 255.
green:color->common.green / 255.
blue:color->common.blue / 255.
alpha:1.0];
poly->poly.color = MwLLAllocColor(handle, color->common.red, color->common.blue, color->common.green);
poly->poly.points_count = points_count;
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:ctx];
poly->poly.points = malloc(sizeof(MwPoint) * points_count);
memcpy(poly->poly.points, points, sizeof(MwPoint) * points_count);
[nscolor setFill];
for(i = 0; i < points_count; i++) {
NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view);
if(i == 0) {
[path moveToPoint:p];
} else {
[path lineToPoint:p];
}
}
arrpush(handle->cocoa.real->view->commands, poly);
[path closePath];
[path fill];
[NSGraphicsContext restoreGraphicsState];
[self->view setNeedsDisplay:YES];
}
[pool release];
[handle->cocoa.real->view setNeedsDisplay:MwTRUE];
}
static void MwLLLineImpl(MwLL handle, MwPoint* points, MwLLColor color) {
MilskoCocoa* self = handle->cocoa.real;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSGraphicsContext* ctx = [self->view context];
if(ctx) {
int i;
NSBezierPath* path = [NSBezierPath bezierPath];
/* whatever rect we use for coordinate flipping */
NSRect _rect = self->parent ? [self->view bounds] : [self->window frame];
draw_command* lines = malloc(sizeof(draw_command));
lines->type = COCOA_DRAW_COMMAND_LINES;
NSColor* nscolor =
[NSColor colorWithCalibratedRed:color->common.red / 255.
green:color->common.green / 255.
blue:color->common.blue / 255.
alpha:1.0];
lines->lines.color = MwLLAllocColor(handle, color->common.red, color->common.blue, color->common.green);
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:ctx];
lines->lines.points = malloc(sizeof(MwPoint) * 2);
memcpy(lines->lines.points, points, sizeof(MwPoint) * 2);
[nscolor setFill];
for(i = 0; i < 2; i++) {
NSPoint p = localPointFlip(NSMakePoint(points[i].x, points[i].y), self->view);
if(i == 0) {
[path moveToPoint:p];
} else {
[path lineToPoint:p];
}
}
[path closePath];
[path stroke];
[NSGraphicsContext restoreGraphicsState];
[self->view setNeedsDisplay:YES];
}
[pool release];
arrpush(handle->cocoa.real->view->commands, lines);
[handle->cocoa.real->view setNeedsDisplay:MwTRUE];
}
static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) {
@ -971,26 +916,15 @@ static void MwLLDestroyPixmapImpl(MwLLPixmap pixmap) {
}
static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
MilskoCocoa* self = handle->cocoa.real;
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
MilskoCocoaPixmap* p = pixmap->cocoa.real;
NSGraphicsContext* ctx = [self->view context];
if(ctx) {
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:ctx];
draw_command* pix = malloc(sizeof(draw_command));
pix->type = COCOA_DRAW_COMMAND_PIXMAP;
[p->image
drawInRect:localRectFlip(NSMakeRect(rect->x, rect->y, rect->width, rect->height), self->view)
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0];
pix->pixmap.rect = *rect;
/* copy the pixmap into a new object that we'll free later */
pix->pixmap.pixmap = MwLLCreatePixmap(handle, pixmap->common.raw, pixmap->common.width, pixmap->common.height);
[NSGraphicsContext restoreGraphicsState];
[self->view setNeedsDisplay:YES];
}
[pool release];
MwLLForceRender(handle);
arrpush(handle->cocoa.real->view->commands, pix);
[handle->cocoa.real->view setNeedsDisplay:MwTRUE];
}
static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) {