1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "FrameBufferOSX.hpp"
16
17#include "Common/Debug.hpp"
18
19#include <EGL/egl.h>
20#import <QuartzCore/QuartzCore.h>
21
22namespace sw {
23
24	FrameBufferOSX::FrameBufferOSX(CALayer* layer, int width, int height)
25		: FrameBuffer(width, height, false, false), width(width), height(height),
26		  layer(layer), buffer(nullptr), provider(nullptr), currentImage(nullptr)
27	{
28		format = sw::FORMAT_X8B8G8R8;
29		int bufferSize = width * height * 4 * sizeof(uint8_t);
30		buffer = new uint8_t[bufferSize];
31		provider = CGDataProviderCreateWithData(nullptr, buffer, bufferSize, nullptr);
32		colorspace = CGColorSpaceCreateDeviceRGB();
33	}
34
35	FrameBufferOSX::~FrameBufferOSX()
36	{
37		//[CATransaction begin];
38		//[layer setContents:nullptr];
39		//[CATransaction commit];
40
41		CGImageRelease(currentImage);
42		CGColorSpaceRelease(colorspace);
43		CGDataProviderRelease(provider);
44
45		delete[] buffer;
46	}
47
48	void FrameBufferOSX::flip(sw::Surface *source)
49	{
50		blit(source, nullptr, nullptr);
51	}
52
53	void FrameBufferOSX::blit(sw::Surface *source, const Rect *sourceRect, const Rect *destRect)
54	{
55		copy(source);
56
57		int bytesPerRow = width * 4 * sizeof(uint8_t);
58		CGImageRef image = CGImageCreate(width, height, 8, 32, bytesPerRow, colorspace, kCGBitmapByteOrder32Big, provider, nullptr, false, kCGRenderingIntentDefault);
59
60		[CATransaction begin];
61		[layer setContents:(id)image];
62		[CATransaction commit];
63		[CATransaction flush];
64
65		if(currentImage)
66		{
67			CGImageRelease(currentImage);
68		}
69		currentImage = image;
70	}
71
72	void *FrameBufferOSX::lock()
73	{
74		stride = width * 4 * sizeof(uint8_t);
75		framebuffer = buffer;
76		return framebuffer;
77	};
78
79	void FrameBufferOSX::unlock()
80	{
81		framebuffer = nullptr;
82	};
83}
84
85sw::FrameBuffer *createFrameBuffer(void *display, EGLNativeWindowType nativeWindow, int width, int height)
86{
87	NSObject *window = reinterpret_cast<NSObject*>(nativeWindow);
88	CALayer *layer = nullptr;
89
90	if([window isKindOfClass:[NSView class]])
91	{
92		NSView *view = reinterpret_cast<NSView*>(window);
93		[view setWantsLayer:YES];
94		layer = [view layer];
95	}
96	else if([window isKindOfClass:[CALayer class]])
97	{
98		layer = reinterpret_cast<CALayer*>(window);
99	}
100	else ASSERT(0);
101
102	return new sw::FrameBufferOSX(layer, width, height);
103}
104