<commit_before>#include "common.h"
#include "rendertarget.h"
#import <IOSurface/IOSurface.h>
#import <IOSurface/IOSurfaceObjC.h>

#include <OpenGL/CGLIOSurface.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>

@interface IOSurfaceHolder : NSObject
@end

@implementation IOSurfaceHolder
{
    @public IOSurfaceRef surface;
    @public AvnPixelSize size;
    @public float scale;
    ComPtr<IAvnGlContext> _context;
    GLuint _framebuffer, _texture, _renderbuffer;
}

- (IOSurfaceHolder*) initWithSize: (AvnPixelSize) size
                        withScale: (float)scale
                withOpenGlContext: (IAvnGlContext*) context
{
    long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.Width * 4);
    long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.Height * bytesPerRow);
    NSDictionary* options = @{
                              (id)kIOSurfaceWidth: @(size.Width),
                              (id)kIOSurfaceHeight:  @(size.Height),
                              (id)kIOSurfacePixelFormat: @((uint)'BGRA'),
                              (id)kIOSurfaceBytesPerElement: @(4),
                              (id)kIOSurfaceBytesPerRow: @(bytesPerRow),
                              (id)kIOSurfaceAllocSize: @(allocSize),
                              
                              //(id)kIOSurfaceCacheMode: @(kIOMapWriteCombineCache),
                              (id)kIOSurfaceElementWidth: @(1),
                              (id)kIOSurfaceElementHeight: @(1)
                              };
    
    surface = IOSurfaceCreate((CFDictionaryRef)options);
    self->scale = scale;
    self->size = size;
    self->_context = context;
    return self;
}

-(HRESULT) prepareForGlRender
{
    if(_context == nil)
        return E_FAIL;
    if(CGLGetCurrentContext() != _context->GetNativeHandle())
        return E_FAIL;
    if(_framebuffer == 0)
        glGenFramebuffersEXT(1, &_framebuffer);
    
    
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _framebuffer);
    if(_texture == 0)
    {
        glGenTextures(1, &_texture);
    
        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
        CGLError res = CGLTexImageIOSurface2D((CGLContextObj)_context->GetNativeHandle(),
                               GL_TEXTURE_RECTANGLE_EXT, GL_RGBA8,
                               size.Width, size.Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0);
        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
        
        if(res != 0)
        {
            glDeleteTextures(1, &_texture);
            _texture = 0;
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
            return E_FAIL;
        }
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, _texture, 0);
    }
    
    if(_renderbuffer == 0)
    {
        glGenRenderbuffers(1, &_renderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.Width, size.Height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderbuffer);
    }
    
    return S_OK;
}

-(void) finishDraw
{
    ComPtr<IUnknown> release;
    _context->MakeCurrent(release.getPPV());
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    glFlush();
}

-(void) dealloc
{
    
    if(_framebuffer != 0)
    {
        ComPtr<IUnknown> release;
        _context->MakeCurrent(release.getPPV());
        glDeleteFramebuffers(1, &_framebuffer);
        if(_texture != 0)
            glDeleteTextures(1, &_texture);
        if(_renderbuffer != 0)
            glDeleteRenderbuffers(1, &_renderbuffer);
    }
    CFRelease(surface);
}
@end

static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* target);

@implementation IOSurfaceRenderTarget
{
    CALayer* _layer;
    @public IOSurfaceHolder* surface;
    @public NSObject* lock;
    ComPtr<IAvnGlContext> _glContext;
}

- (IOSurfaceRenderTarget*) initWithOpenGlContext: (IAvnGlContext*) context;
{
    self = [super init];
    _glContext = context;
    lock = [NSObject new];
    surface  = nil;
    [self resize:{1,1} withScale: 1];
    
    return self;
}

- (AvnPixelSize) pixelSize {
    return {1, 1};
}

- (CALayer *)layer {
    return _layer;
}

- (void)resize:(AvnPixelSize)size withScale: (float) scale;{
    @synchronized (lock) {
        if(surface == nil
           || surface->size.Width != size.Width
           || surface->size.Height != size.Height
           || surface->scale != scale)
            surface = [[IOSurfaceHolder alloc] initWithSize:size withScale:scale withOpenGlContext:_glContext.getRaw()];
    }
}

- (void)updateLayer {
    if ([NSThread isMainThread])
    {
        @synchronized (lock) {<commit_msg>[OSX] remove most of the stretching and flickering by calling updateLayer at the end of resize.<commit_after>#include "common.h"
#include "rendertarget.h"
#import <IOSurface/IOSurface.h>
#import <IOSurface/IOSurfaceObjC.h>

#include <OpenGL/CGLIOSurface.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/glext.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>

@interface IOSurfaceHolder : NSObject
@end

@implementation IOSurfaceHolder
{
    @public IOSurfaceRef surface;
    @public AvnPixelSize size;
    @public float scale;
    ComPtr<IAvnGlContext> _context;
    GLuint _framebuffer, _texture, _renderbuffer;
}

- (IOSurfaceHolder*) initWithSize: (AvnPixelSize) size
                        withScale: (float)scale
                withOpenGlContext: (IAvnGlContext*) context
{
    long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.Width * 4);
    long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.Height * bytesPerRow);
    NSDictionary* options = @{
                              (id)kIOSurfaceWidth: @(size.Width),
                              (id)kIOSurfaceHeight:  @(size.Height),
                              (id)kIOSurfacePixelFormat: @((uint)'BGRA'),
                              (id)kIOSurfaceBytesPerElement: @(4),
                              (id)kIOSurfaceBytesPerRow: @(bytesPerRow),
                              (id)kIOSurfaceAllocSize: @(allocSize),
                              
                              //(id)kIOSurfaceCacheMode: @(kIOMapWriteCombineCache),
                              (id)kIOSurfaceElementWidth: @(1),
                              (id)kIOSurfaceElementHeight: @(1)
                              };
    
    surface = IOSurfaceCreate((CFDictionaryRef)options);
    self->scale = scale;
    self->size = size;
    self->_context = context;
    return self;
}

-(HRESULT) prepareForGlRender
{
    if(_context == nil)
        return E_FAIL;
    if(CGLGetCurrentContext() != _context->GetNativeHandle())
        return E_FAIL;
    if(_framebuffer == 0)
        glGenFramebuffersEXT(1, &_framebuffer);
    
    
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _framebuffer);
    if(_texture == 0)
    {
        glGenTextures(1, &_texture);
    
        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
        CGLError res = CGLTexImageIOSurface2D((CGLContextObj)_context->GetNativeHandle(),
                               GL_TEXTURE_RECTANGLE_EXT, GL_RGBA8,
                               size.Width, size.Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0);
        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
        
        if(res != 0)
        {
            glDeleteTextures(1, &_texture);
            _texture = 0;
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
            return E_FAIL;
        }
        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, _texture, 0);
    }
    
    if(_renderbuffer == 0)
    {
        glGenRenderbuffers(1, &_renderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.Width, size.Height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderbuffer);
    }
    
    return S_OK;
}

-(void) finishDraw
{
    ComPtr<IUnknown> release;
    _context->MakeCurrent(release.getPPV());
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    glFlush();
}

-(void) dealloc
{
    
    if(_framebuffer != 0)
    {
        ComPtr<IUnknown> release;
        _context->MakeCurrent(release.getPPV());
        glDeleteFramebuffers(1, &_framebuffer);
        if(_texture != 0)
            glDeleteTextures(1, &_texture);
        if(_renderbuffer != 0)
            glDeleteRenderbuffers(1, &_renderbuffer);
    }
    CFRelease(surface);
}
@end

static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* target);

@implementation IOSurfaceRenderTarget
{
    CALayer* _layer;
    @public IOSurfaceHolder* surface;
    @public NSObject* lock;
    ComPtr<IAvnGlContext> _glContext;
}

- (IOSurfaceRenderTarget*) initWithOpenGlContext: (IAvnGlContext*) context;
{
    self = [super init];
    _glContext = context;
    lock = [NSObject new];
    surface  = nil;
    [self resize:{1,1} withScale: 1];
    
    return self;
}

- (AvnPixelSize) pixelSize {
    return {1, 1};
}

- (CALayer *)layer {
    return _layer;
}

- (void)resize:(AvnPixelSize)size withScale: (float) scale{
    @synchronized (lock) {
        if(surface == nil
           || surface->size.Width != size.Width
           || surface->size.Height != size.Height
           || surface->scale != scale)
        {
            surface = [[IOSurfaceHolder alloc] initWithSize:size withScale:scale withOpenGlContext:_glContext.getRaw()];
            
            [self updateLayer];
        }
    }
}

- (void)updateLayer {
    if ([NSThread isMainThread])
    {
        @synchronized (lock) {
{'fraction_non_alphanumeric': 0.10767503572157583, 'fraction_numerical': 0.007960808328230252, 'mean_word_length': 2.524820143884892, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3512406', 'n_tokens_mistral': 3251, 'n_tokens_neox': 3103, 'n_words': 521}