Skip to content

Commit

Permalink
Don't use refs for unmanaged bitmaps
Browse files Browse the repository at this point in the history
  • Loading branch information
Nycto committed Oct 19, 2024
1 parent 1a752d3 commit 7dd8e6e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 30 deletions.
4 changes: 2 additions & 2 deletions playdate_example/src/playdate_example.nim
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ proc handler(event: PDSystemEvent, keycode: uint) {.raises: [].} =
font = try: playdate.graphics.newFont(FONT_PATH) except: nil
playdate.graphics.setFont(font)

playdateNimBitmap = try: playdate.graphics.newBitmap(PLAYDATE_NIM_IMAGE_PATH) except: nil
nimLogoBitmap = try: playdate.graphics.newBitmap(NIM_IMAGE_PATH) except: nil
playdateNimBitmap = try: playdate.graphics.newBitmap(PLAYDATE_NIM_IMAGE_PATH) except: return
nimLogoBitmap = try: playdate.graphics.newBitmap(NIM_IMAGE_PATH) except: return

sprite = playdate.sprite.newSprite()
sprite.add()
Expand Down
80 changes: 55 additions & 25 deletions src/playdate/graphics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,49 @@ export graphics
{.hint[DuplicateModuleImport]: off.}
import bindings/graphics {.all.}

type LCDBitmapObj = object of RootObj
resource {.requiresinit.}: LCDBitmapPtr
free: bool
type
LCDBitmapObj = object of RootObj
res {.requiresinit.}: LCDBitmapPtr

LCDBitmapObjRef = ref LCDBitmapObj

LCDBitmap* = object
case managed: bool
of true:
obj: LCDBitmapObjRef
of false:
res: LCDBitmapPtr

proc `=destroy`(this: var LCDBitmapObj) =
privateAccess(PlaydateGraphics)
if this.free:
playdate.graphics.freeBitmap(this.resource)
type LCDBitmap* = ref LCDBitmapObj
if this.res != nil:
playdate.graphics.freeBitmap(this.res)

proc `=copy`(a: var LCDBitmapObj, b: LCDBitmapObj) {.error.}

proc newUnmanagedBitmap(point: LCDBitmapPtr): auto =
LCDBitmap(managed: false, res: point)

proc newManagedBitmap(point: LCDBitmapPtr): auto =
LCDBitmap(managed: true, obj: LCDBitmapObjRef(res: point))

proc resource*(bitmap: LCDBitmap): LCDBitmapPtr =
if bitmap.managed:
return if bitmap.obj != nil: bitmap.obj.res else: nil
else:
return bitmap.res

proc isNil*(bitmap: LCDBitmap): bool =
return bitmap.resource == nil

type LCDVideoPlayerObj = object of RootObj
resource {.requiresinit.}: LCDVideoPlayerPtr
context: LCDBitmap

proc `=destroy`(this: var LCDVideoPlayerObj) =
privateAccess(PlaydateVideo)
playdate.graphics.video.freePlayer(this.resource)
this.context = nil
this.context.reset()
type LCDVideoPlayer* = ref LCDVideoPlayerObj

proc newVideoPlayer*(this: ptr PlaydateVideo, path: string): LCDVideoPlayer {.raises: [IOError]} =
Expand All @@ -38,14 +65,14 @@ proc newVideoPlayer*(this: ptr PlaydateVideo, path: string): LCDVideoPlayer {.ra

proc setContext*(this: LCDVideoPlayer, context: LCDBitmap) {.raises: [CatchableError]} =
privateAccess(PlaydateVideo)
if playdate.graphics.video.setContext(this.resource, if context != nil: context.resource else: nil) == 0:
if playdate.graphics.video.setContext(this.resource, context.resource) == 0:
raise newException(CatchableError, $playdate.graphics.video.getError(this.resource))
this.context = context

proc useScreenContext*(this: LCDVideoPlayer) =
privateAccess(PlaydateVideo)
playdate.graphics.video.useScreenContext(this.resource)
this.context = nil
this.context.reset()

proc renderFrame*(this: LCDVideoPlayer, index: int) {.raises: [CatchableError]} =
privateAccess(PlaydateVideo)
Expand All @@ -63,8 +90,8 @@ proc getContext*(this: LCDVideoPlayer): LCDBitmap =
privateAccess(PlaydateVideo)
let bitmapPtr = playdate.graphics.video.getContext(this.resource)
playdate.system.logToConsole(fmt"video context: {bitmapPtr.repr}")
if this.context == nil or this.context.resource != bitmapPtr:
this.context = LCDBitmap(resource: bitmapPtr, free: false)
if this.context.isNil or this.context.resource != bitmapPtr:
this.context = newUnmanagedBitmap(bitmapPtr)
return this.context

var currentFont: LCDFont
Expand All @@ -80,7 +107,7 @@ proc getFont*(this: ptr PlaydateGraphics): LCDFont =

proc pushContext*(this: ptr PlaydateGraphics, target: LCDBitmap) =
privateAccess(PlaydateGraphics)
this.pushContext(if target != nil: target.resource else: nil)
this.pushContext(target.resource)

proc draw*(this: LCDBitmap, x: int, y: int, flip: LCDBitmapFlip) =
privateAccess(PlaydateGraphics)
Expand All @@ -105,19 +132,19 @@ proc drawText*(

proc newBitmap*(this: ptr PlaydateGraphics, width: int, height: int, color: LCDColor): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: this.newBitmap(width.cint, height.cint, color.convert), free: true)
return newManagedBitmap(this.newBitmap(width.cint, height.cint, color.convert))

proc newBitmap*(this: ptr PlaydateGraphics, path: string): LCDBitmap {.raises: [IOError]} =
privateAccess(PlaydateGraphics)
var err: ConstChar = nil
let bitmap = LCDBitmap(resource: this.loadBitmap(path, addr(err)), free: true)
let bitmap = newManagedBitmap(this.loadBitmap(path, addr(err)))
if bitmap.resource == nil:
raise newException(IOError, $err)
return bitmap

proc copy*(this: LCDBitmap): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: playdate.graphics.copyBitmap(this.resource), free: true)
return newManagedBitmap(playdate.graphics.copyBitmap(this.resource))

proc load*(this: LCDBitmap, path: string) {.raises: [IOError]} =
privateAccess(PlaydateGraphics)
Expand Down Expand Up @@ -148,7 +175,7 @@ template read(bitmap: AnyBitmapData, x, y: int): untyped =
proc getDataObj*(this: LCDBitmap): BitmapDataObj =
## Fetch the underlying bitmap data for an image.
privateAccess(PlaydateGraphics)
assert(this != nil)
assert(not this.isNil)
assert(this.resource != nil)
playdate.graphics.getBitmapData(
this.resource,
Expand All @@ -166,7 +193,10 @@ proc getData*(this: LCDBitmap): BitmapData =

proc getSize*(this: LCDBitmap): tuple[width: int, height: int] =
privateAccess(PlaydateGraphics)
assert(this != nil)

if this.isNil:
assert(not this.isNil)

assert(this.resource != nil)
var width, height: cint
playdate.graphics.getBitmapData(this.resource, addr(width), addr(height), nil,
Expand All @@ -181,8 +211,8 @@ proc rotated*(this: LCDBitmap, rotation: float32, xScale: float32, yScale: float
tuple[bitmap: LCDBitmap, allocatedSize: int] =
privateAccess(PlaydateGraphics)
var allocatedSize: cint
let bitmap = LCDBitmap(resource: playdate.graphics.rotatedBitmap(this.resource, rotation.cfloat, xScale.cfloat, yScale.cfloat,
addr(allocatedSize)), free: true)
let bitmap = newManagedBitmap(playdate.graphics.rotatedBitmap(this.resource, rotation.cfloat, xScale.cfloat, yScale.cfloat,
addr(allocatedSize)))
return (bitmap, allocatedSize.int)

proc rotated*(this: LCDBitmap, rotation: float32, scale: float32):
Expand Down Expand Up @@ -232,8 +262,8 @@ proc getBitmap*(this: LCDBitmapTable, index: int): LCDBitmap =
privateAccess(PlaydateGraphics)
let resource = playdate.graphics.getTableBitmap(this.resource, index.cint)
if resource != nil:
return LCDTableBitmap(resource: resource, free: false, table: this)
return nil
return newUnmanagedBitmap(resource)
return default(LCDBitmap)

proc getBitmapTableInfo*(this: LCDBitmapTable): tuple[count: int, cellsWide: int] =
privateAccess(PlaydateGraphics)
Expand Down Expand Up @@ -341,11 +371,11 @@ proc set*(view: var BitmapView, x, y: int, color: LCDSolidColor) =

proc getDebugBitmap*(this: ptr PlaydateGraphics): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: this.getDebugBitmap(), free: true) # Who should manage this memory? Not clear. Auto-managed.
return newManagedBitmap(this.getDebugBitmap()) # Who should manage this memory? Not clear. Auto-managed.

proc copyFrameBufferBitmap*(this: ptr PlaydateGraphics): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: this.copyFrameBufferBitmap(), free: true)
return newManagedBitmap(this.copyFrameBufferBitmap())

proc createPattern*(this: ptr PlaydateGraphics, bitmap: LCDBitmap, x: int, y: int): LCDPattern =
privateAccess(PlaydateGraphics)
Expand All @@ -369,7 +399,7 @@ proc getFontHeight*(this: LCDFont): uint =

proc getDisplayBufferBitmap*(this: ptr PlaydateGraphics): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: this.getDisplayBufferBitmap(), free: false)
return newUnmanagedBitmap(this.getDisplayBufferBitmap())

proc drawRotated*(this: LCDBitmap, x: int, y: int, rotation: float32, centerX: float32, centerY:
float32, xScale: float32, yScale: float32) =
Expand All @@ -390,7 +420,7 @@ proc setBitmapMask*(

proc getBitmapMask*(this: LCDBitmap): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: playdate.graphics.getBitmapMask(this.resource), free: false) # Who should manage this memory? Not clear. Not auto-managed right now.
return newUnmanagedBitmap(playdate.graphics.getBitmapMask(this.resource))

proc get*(this: LCDBitmap, x, y: int): LCDSolidColor =
## Reads the color of a bitmap, taking into account the color mask
Expand Down
6 changes: 3 additions & 3 deletions src/playdate/sprite.nim
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ proc bounds*(this: LCDSprite): PDRect =
proc setImage*(this: LCDSprite, image: LCDBitmap, flip: LCDBitmapFlip) =
privateAccess(PlaydateSprite)
privateAccess(LCDBitmap)
playdate.sprite.setImage(this.resource, if image != nil: image.resource else: nil, flip)
playdate.sprite.setImage(this.resource, image.resource, flip)
this.bitmap = image

proc getImage*(this: LCDSprite): LCDBitmap =
Expand Down Expand Up @@ -404,12 +404,12 @@ proc setStencilPattern*(this: LCDSprite, pattern: array[8, uint8]) =
proc clearStencil*(this: LCDSprite) =
privateAccess(PlaydateSprite)
playdate.sprite.clearStencil(this.resource)
this.stencil = nil
this.stencil.reset()

proc setStencilImage*(this: LCDSprite, stencil: LCDBitmap, tile: bool) =
privateAccess(PlaydateSprite)
privateAccess(LCDBitmap)
playdate.sprite.setStencilImage(this.resource, if stencil != nil: stencil.resource else: nil, if tile: 1 else: 0)
playdate.sprite.setStencilImage(this.resource, stencil.resource, if tile: 1 else: 0)
this.stencil = stencil

proc setCenter*(this: LCDSprite, x: float32, y: float32) =
Expand Down

0 comments on commit 7dd8e6e

Please sign in to comment.