Skip to content

Abstract BitmapData to allow ram dumping #3540

Open

Description

@Geokureli

Rough Idea

Deprecate myFlxGraphic.bitmap, any other uses of Bitmap and add some graphic.startManipulation() method which returns an object with Bitmap's drawing tools, which somehow requires a finalizing end() call to dumb the Ram

Activity

  1. added theissue type on Dec 26, 2025
  2. ACrazyTown commented on Dec 26, 2025

    @ACrazyTown
    Contributor

    Some food for thought, here's how a couple different frameworks/engines tackle this:

    • Unity
      • There's a single Texture2D class, hardware-only by default, that handles both the software pixels and GPU texture. I guess in this way it's similar to OpenFL's BitmapData
      • Use Texture2D.ReadPixels() to download the pixels from the GPU, do whatever edits, and then Texture2D.Apply() to upload it back to the GPU (and optionally dump the software pixels)
    • Godot
    • Heaps
      • Similarly to Flash, has a BitmapData class for software pixels. In order to be used for rendering, it needs to be turned into a Texture first.
      • Also has methods to download and upload pixel data.

    I think for Flixel 7 we could consider making FlxGraphic use hardware textures only by default, since most people don't need to edit graphics. Readable textures could be requested with an optional parameter to some method, or we could add a new method to download the pixel data back from the GPU.

  3. Geokureli commented on Jan 2, 2026

    @Geokureli
    MemberAuthor

    I'm leaning towards:

    final tex:FlxTexture = FlxG.assets.getTexture(assetPath);
    final bitmap:FlxBitmap = tex.getBitmap();
    // draw to itself with inverted colors using the forwarded (or similarly defined) BitmapData.draw
    bitmap.draw(bitmap, null, invertColorTransform);
    tex.apply(); // apply(dump = true)
    
    // ALL of the following names suck
    switch tex.status
    {
         case LOCKED:
              trace("The Texture is only in VRAM"); // Should be in this state, because it was dumped in the apply() call
         case UNLOCKED(bitmap, true):
              trace("The** texture exists in both RAM and VRAM, and they are synced");
         case UNLOCKED(bitmap, false):
              // not possible in openfl?
              trace("The texture exists in both RAM and VRAM, which was edited, and not yet applied");
    }

    or maybe tex.bitmapStatus and instead of locked/unlocked we can use DUMPED, FLUSHED or HARDWARE?

    I feel like with this way, we can keep existing things in tact for a while. FlxG.assets.getBitmapData can still return a bitmap which can be passed into sprites and junk, and there's a way for things n the backend to get the texture from the bitmap (or create one if the dev used new BitmapData()). FlxGraphic will use textures instead of bitmaps, but if the (now deprecated) graphic.bitmap getter is invoked it creates the instance and leaves it undumped and editable. We don't really need an "apply" method for openfl, it seems like they are auto applied, but other backends may need this; openfl really just needs a way to dump the ram when you're done

  4. ACrazyTown commented on Jan 4, 2026

    @ACrazyTown
    Contributor

    I'm a fan of that snippet, I think that might be the way to go.

    Maybe instead of a status variable and an enum we can do something similarly to OpenFL and Unity and have a readable bool. If true, there is a present bitmap we can read/write to, otherwise it's a texture only.

    We don't really need an "apply" method for openfl, it seems like they are auto applied

    This is true, the texture is updated the next time bitmapData.getTexture() is called, which is usually when it gets rendered. We could just force the texture upload immediately though, for consistency.

  5. Geokureli commented on Jan 5, 2026

    @Geokureli
    MemberAuthor

    The reason I prefer enums is A: It allows context specific fields, rather than a series of bools and nullable fields that may not apply to the current context and B: It's easy to add new cases when we discover gaps, that may require more context specific fields. The non-enum equivalent could consist of hasUnappliedChanges:Bool, readable:Bool and/or currentBitmap:Null<FlxBitmap>, compared to the non-nullable bitmap field of the enum

    We could just force the texture upload immediately though, for consistency.

    It'd be nice if we could prevent the auto upload on openfl, but this isn't a big deal, could also add a autoAppliesChanges getter or a third value for the second arg of the UNLOCKED state

  6. ACrazyTown commented on Jan 19, 2026

    @ACrazyTown
    Contributor

    I'm playing around trying to implement these changes, but I'm a bit confused on how abstracting some of the BitmapData methods would go. I'd assume that we'd switch out any reference to OpenFL types with their Flixel equivalents, and while that's mostly a 1:1 map (i.e. Rectangle -> FlxRect, Point -> FlxPoint), there are some types that don't have a direct equivalent.

    Let's take these two methods from BitmapData for example:

    public function draw(source:IBitmapDrawable, matrix:Matrix = null, colorTransform:ColorTransform = null, blendMode:BlendMode = null, clipRect:Rectangle = null, smoothing:Bool = false):Void
    
    public function applyFilter(sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, filter:BitmapFilter):Void

    How would IBitmapDrawable, ColorTransform and BitmapFilter be represented, without relying on OpenFL/Flash types? Of course, we don't have to match the function signatures 1:1, but by not doing that we're kinda sacrificing compatibility and feature parity. Maybe we shouldn't bother trying to hook up all the fancy methods, and make it possible to access the BitmapData reference for advanced drawing instead?

    FWIW this is a rough draft I have right now:

    abstract FlxBitmap(BitmapData)
    {
        public function fillRect(rect:FlxRect, color:FlxColor):Void
        {
            var flashRect = Rectangle.__pool.get();
            rect.copyToFlash(flashRect);
    
            this.fillRect(flashRect, color);
    
            Rectangle.__pool.release(flashRect);
        }
    
        public inline function setPixel(x:Int, y:Int, color:FlxColor):FlxColor
        {
            this.setPixel32(x, y, color);
        }
    
        public inline function getPixel(x:Int, y:Int):FlxColor
        {
            this.getPixel32(x, y);
        }
    
        public inline function destroy():Void
        {
            // Never actually dispose the BitmapData because we use it for rendering as well
            // this.dispose();
            this.disposeImage();
        }
    }
  7. Geokureli commented on Jan 19, 2026

    @Geokureli
    MemberAuthor

    I was thinking either A: Use typedefs for the missing types, I.E.: IFlxBitmapDrawable or B: Just expose BitmapData and further abstract it later. Whichever seems simpler. I think exposing BitmapData is likely the simplest, our near-goal is to allow texture dumping, while still allowing them to enable bitmap manipulations. Setting up different backends is the far away goal

    Edit: I think FlxBitmap will need to be an abstract, like in your example. We will keep adding to it, but I'm not afraid of forwarding (most) functions, so long that we hide the confusing dispose stuff

  8. ACrazyTown commented on Jan 19, 2026

    @ACrazyTown
    Contributor

    I think exposing BitmapData is likely the simplest, our near-goal is to allow texture dumping, while still allowing them to enable bitmap manipulations. Setting up different backends is the far away goal

    Fair enough, I've been keeping all these goals in mind to try and future proof stuff to make it easier to deal with in the long run. Would it be safe to assume that the backend abstraction stuff would be reserved for a major version release?

  9. Geokureli commented on Jan 20, 2026

    @Geokureli
    MemberAuthor

    Would it be safe to assume that the backend abstraction stuff would be reserved for a major version release?

    It's hard to imagine otherwise, but not impossible. In fact, often the breaking changes are for things we've already introduced in minor versions. It would be nice if we introduced FlxBitmap, long before we strip away Bitmaps, so devs can migrate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions