From 6c283e81dfb6af5b84978194c5ec1a6b0572c2b9 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 21 Oct 2013 22:18:59 -0700 Subject: [PATCH] Add methods to bind to textures and upload data --- io_surface.rc | 143 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 104 insertions(+), 39 deletions(-) diff --git a/io_surface.rc b/io_surface.rc index d5815cb..51151b1 100644 --- a/io_surface.rc +++ b/io_surface.rc @@ -12,26 +12,35 @@ #[crate_type = "lib"]; extern mod core_foundation; +extern mod geom; +extern mod opengles; extern mod std; // Rust bindings to the IOSurface framework on Mac OS X. -use core_foundation::base::{ - AbstractCFTypeRef, - CFTypeID, - CFTypeRef, - CFWrapper, -}; -use core_foundation::dictionary::{ - CFDictionaryRef, - UntypedCFDictionary}; +use core_foundation::base::{AbstractCFTypeRef, CFTypeID, CFTypeRef, CFWrapper}; +use core_foundation::dictionary::{CFDictionaryRef, UntypedCFDictionary}; use core_foundation::string::CFStringRef; +use geom::size::Size2D; +use opengles::cgl::{kCGLNoError, CGLGetCurrentContext, CGLTexImageIOSurface2D}; +use opengles::gl2::{BGRA, GLenum, GLsizei, RGBA, TEXTURE_RECTANGLE_ARB, UNSIGNED_INT_8_8_8_8_REV}; +use std::cast; +use std::libc::{c_int, c_void, size_t}; +use std::vec::bytes; + +static kIOSurfaceLockReadOnly: u32 = 0x1; +static kIOSurfaceLockAvoidSync: u32 = 0x2; + +type IOReturn = c_int; struct __IOSurface { private: () } + pub type IOSurfaceRef = *__IOSurface; impl AbstractCFTypeRef for IOSurfaceRef { - fn as_type_ref(&self) -> CFTypeRef { *self as CFTypeRef } + fn as_type_ref(&self) -> CFTypeRef { + *self as CFTypeRef + } #[fixed_stack_segment] fn type_id(_dummy: Option) -> CFTypeID { @@ -41,19 +50,28 @@ impl AbstractCFTypeRef for IOSurfaceRef { } } -pub type IOSurface = CFWrapper; +pub struct IOSurface { + contents: CFWrapper, +} pub type IOSurfaceID = u32; -pub trait IOSurfaceMethods { - fn get_id(&self) -> IOSurfaceID; +impl Clone for IOSurface { + fn clone(&self) -> IOSurface { + IOSurface { + contents: CFWrapper::clone(&self.contents), + } + } } #[fixed_stack_segment] pub fn new(properties: &UntypedCFDictionary) -> IOSurface { unsafe { let result = IOSurfaceCreate(*properties.contents.borrow_ref()); - CFWrapper::wrap_owned(result) + let result = IOSurface { + contents: CFWrapper::wrap_owned(result), + }; + result } } @@ -61,15 +79,55 @@ pub fn new(properties: &UntypedCFDictionary) -> IOSurface { pub fn lookup(csid: IOSurfaceID) -> IOSurface { unsafe { let result = IOSurfaceLookup(csid); - CFWrapper::wrap_owned(result) + IOSurface { + contents: CFWrapper::wrap_owned(result), + } } } -impl IOSurfaceMethods for IOSurface { +impl IOSurface { #[fixed_stack_segment] - fn get_id(&self) -> IOSurfaceID { + pub fn get_id(&self) -> IOSurfaceID { unsafe { - IOSurfaceGetID(self.obj) + IOSurfaceGetID(*self.contents.borrow_ref()) + } + } + + /// Binds to the current GL texture. + #[fixed_stack_segment] + pub fn bind_to_gl_texture(&self, size: Size2D) { + unsafe { + let context = CGLGetCurrentContext(); + let gl_error = CGLTexImageIOSurface2D(context, + TEXTURE_RECTANGLE_ARB, + RGBA as GLenum, + size.width as GLsizei, + size.height as GLsizei, + BGRA as GLenum, + UNSIGNED_INT_8_8_8_8_REV, + cast::transmute(*self.contents.borrow_ref()), + 0); + + assert_eq!(gl_error, kCGLNoError); + } + } + + #[fixed_stack_segment] + pub fn upload(&self, data: &[u8]) { + unsafe { + let surface = *self.contents.borrow_ref(); + let mut seed = 0; + + IOSurfaceLock(surface, 0, &mut seed); + + let height = IOSurfaceGetHeight(surface); + let stride = IOSurfaceGetBytesPerRow(surface); + let size = (height * stride) as uint; + let dest: &mut [u8] = cast::transmute((IOSurfaceGetBaseAddress(surface), size)); + bytes::copy_memory(dest, data, data.len()); + + // FIXME(pcwalton): RAII + IOSurfaceUnlock(surface, 0, &mut seed); } } } @@ -77,35 +135,42 @@ impl IOSurfaceMethods for IOSurface { #[link_args="-framework IOSurface"] #[nolink] extern { - static kIOSurfaceAllocSize: CFStringRef; - static kIOSurfaceWidth: CFStringRef; - static kIOSurfaceHeight: CFStringRef; - static kIOSurfaceBytesPerRow: CFStringRef; - static kIOSurfaceBytesPerElement: CFStringRef; - static kIOSurfaceElementWidth: CFStringRef; - static kIOSurfaceElementHeight: CFStringRef; - static kIOSurfaceOffset: CFStringRef; + pub static kIOSurfaceAllocSize: CFStringRef; + pub static kIOSurfaceWidth: CFStringRef; + pub static kIOSurfaceHeight: CFStringRef; + pub static kIOSurfaceBytesPerRow: CFStringRef; + pub static kIOSurfaceBytesPerElement: CFStringRef; + pub static kIOSurfaceElementWidth: CFStringRef; + pub static kIOSurfaceElementHeight: CFStringRef; + pub static kIOSurfaceOffset: CFStringRef; - static kIOSurfacePlaneInfo: CFStringRef; - static kIOSurfacePlaneWidth: CFStringRef; - static kIOSurfacePlaneHeight: CFStringRef; - static kIOSurfacePlaneBytesPerRow: CFStringRef; - static kIOSurfacePlaneOffset: CFStringRef; - static kIOSurfacePlaneSize: CFStringRef; + pub static kIOSurfacePlaneInfo: CFStringRef; + pub static kIOSurfacePlaneWidth: CFStringRef; + pub static kIOSurfacePlaneHeight: CFStringRef; + pub static kIOSurfacePlaneBytesPerRow: CFStringRef; + pub static kIOSurfacePlaneOffset: CFStringRef; + pub static kIOSurfacePlaneSize: CFStringRef; - static kIOSurfacePlaneBase: CFStringRef; - static kIOSurfacePlaneBytesPerElement: CFStringRef; - static kIOSurfacePlaneElementWidth: CFStringRef; - static kIOSurfacePlaneElementHeight: CFStringRef; + pub static kIOSurfacePlaneBase: CFStringRef; + pub static kIOSurfacePlaneBytesPerElement: CFStringRef; + pub static kIOSurfacePlaneElementWidth: CFStringRef; + pub static kIOSurfacePlaneElementHeight: CFStringRef; - static kIOSurfaceCacheMode: CFStringRef; - static kIOSurfaceIsGlobal: CFStringRef; - static kIOSurfacePixelFormat: CFStringRef; + pub static kIOSurfaceCacheMode: CFStringRef; + pub static kIOSurfaceIsGlobal: CFStringRef; + pub static kIOSurfacePixelFormat: CFStringRef; fn IOSurfaceCreate(properties: CFDictionaryRef) -> IOSurfaceRef; fn IOSurfaceLookup(csid: IOSurfaceID) -> IOSurfaceRef; fn IOSurfaceGetID(buffer: IOSurfaceRef) -> IOSurfaceID; fn IOSurfaceGetTypeID() -> CFTypeID; + + fn IOSurfaceLock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> IOReturn; + fn IOSurfaceUnlock(buffer: IOSurfaceRef, options: u32, seed: *mut u32) -> IOReturn; + + fn IOSurfaceGetHeight(buffer: IOSurfaceRef) -> size_t; + fn IOSurfaceGetBytesPerRow(buffer: IOSurfaceRef) -> size_t; + fn IOSurfaceGetBaseAddress(buffer: IOSurfaceRef) -> *mut c_void; }