Skip to content

Commit

Permalink
ui/cocoa: Do not copy members of pixman image
Browse files Browse the repository at this point in the history
The old CocoaView had an idea of synchronizing the host window
configuration and the guest screen configuration. Here, the guest screen
actually means pixman image given ui/cocoa display implementation.

However, [CocoaView -drawRect:] directly interacts with the pixman
image buffer in reality. There is no such distinction of "host" and
"guest." This change removes the "host" configuration and let drawRect
consistently have the direct reference to pixman image. It allows to
get rid of the error-prone "sync" and reduce code size a bit.

Signed-off-by: Akihiko Odaki <akihiko.odaki@gmail.com>
Message-Id: <20210212000629.28551-1-akihiko.odaki@gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
  • Loading branch information
akihikodaki authored and kraxel committed Feb 19, 2021
1 parent 708b725 commit c0ff29d
Showing 1 changed file with 20 additions and 22 deletions.
42 changes: 20 additions & 22 deletions ui/cocoa.m
Expand Up @@ -70,8 +70,6 @@
typedef struct {
int width;
int height;
int bitsPerComponent;
int bitsPerPixel;
} QEMUScreen;

NSWindow *normalWindow, *about_window;
Expand Down Expand Up @@ -291,7 +289,6 @@ @interface QemuCocoaView : NSView
QEMUScreen screen;
NSWindow *fullScreenWindow;
float cx,cy,cw,ch,cdx,cdy;
CGDataProviderRef dataProviderRef;
pixman_image_t *pixman_image;
BOOL modifiers_state[256];
BOOL isMouseGrabbed;
Expand Down Expand Up @@ -338,8 +335,6 @@ - (id)initWithFrame:(NSRect)frameRect
self = [super initWithFrame:frameRect];
if (self) {

screen.bitsPerComponent = 8;
screen.bitsPerPixel = 32;
screen.width = frameRect.size.width;
screen.height = frameRect.size.height;

Expand All @@ -351,8 +346,7 @@ - (void) dealloc
{
COCOA_DEBUG("QemuCocoaView: dealloc\n");

if (dataProviderRef) {
CGDataProviderRelease(dataProviderRef);
if (pixman_image) {
pixman_image_unref(pixman_image);
}

Expand Down Expand Up @@ -431,18 +425,28 @@ - (void) drawRect:(NSRect) rect
CGContextSetShouldAntialias (viewContextRef, NO);

// draw screen bitmap directly to Core Graphics context
if (!dataProviderRef) {
if (!pixman_image) {
// Draw request before any guest device has set up a framebuffer:
// just draw an opaque black rectangle
CGContextSetRGBFillColor(viewContextRef, 0, 0, 0, 1.0);
CGContextFillRect(viewContextRef, NSRectToCGRect(rect));
} else {
int w = pixman_image_get_width(pixman_image);
int h = pixman_image_get_height(pixman_image);
int bitsPerPixel = PIXMAN_FORMAT_BPP(pixman_image_get_format(pixman_image));
int bitsPerComponent = DIV_ROUND_UP(bitsPerPixel, 8) * 2;
CGDataProviderRef dataProviderRef = CGDataProviderCreateWithData(
NULL,
pixman_image_get_data(pixman_image),
w * 4 * h,
NULL
);
CGImageRef imageRef = CGImageCreate(
screen.width, //width
screen.height, //height
screen.bitsPerComponent, //bitsPerComponent
screen.bitsPerPixel, //bitsPerPixel
(screen.width * (screen.bitsPerComponent/2)), //bytesPerRow
w, //width
h, //height
bitsPerComponent, //bitsPerComponent
bitsPerPixel, //bitsPerPixel
(w * (bitsPerComponent/2)), //bytesPerRow
#ifdef __LITTLE_ENDIAN__
CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), //colorspace for OS X >= 10.4
kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst,
Expand All @@ -465,7 +469,7 @@ - (void) drawRect:(NSRect) rect
[self getRectsBeingDrawn:&rectList count:&rectCount];
for (i = 0; i < rectCount; i++) {
clipRect.origin.x = rectList[i].origin.x / cdx;
clipRect.origin.y = (float)screen.height - (rectList[i].origin.y + rectList[i].size.height) / cdy;
clipRect.origin.y = (float)h - (rectList[i].origin.y + rectList[i].size.height) / cdy;
clipRect.size.width = rectList[i].size.width / cdx;
clipRect.size.height = rectList[i].size.height / cdy;
clipImageRef = CGImageCreateWithImageInRect(
Expand All @@ -476,6 +480,7 @@ - (void) drawRect:(NSRect) rect
CGImageRelease (clipImageRef);
}
CGImageRelease (imageRef);
CGDataProviderRelease(dataProviderRef);
}
}

Expand Down Expand Up @@ -518,7 +523,6 @@ - (void) switchSurface:(pixman_image_t *)image

int w = pixman_image_get_width(image);
int h = pixman_image_get_height(image);
pixman_format_code_t image_format = pixman_image_get_format(image);
/* cdx == 0 means this is our very first surface, in which case we need
* to recalculate the content dimensions even if it happens to be the size
* of the initial empty window.
Expand All @@ -536,17 +540,11 @@ - (void) switchSurface:(pixman_image_t *)image
}

// update screenBuffer
if (dataProviderRef) {
CGDataProviderRelease(dataProviderRef);
if (pixman_image) {
pixman_image_unref(pixman_image);
}

//sync host window color space with guests
screen.bitsPerPixel = PIXMAN_FORMAT_BPP(image_format);
screen.bitsPerComponent = DIV_ROUND_UP(screen.bitsPerPixel, 8) * 2;

pixman_image = image;
dataProviderRef = CGDataProviderCreateWithData(NULL, pixman_image_get_data(image), w * 4 * h, NULL);

// update windows
if (isFullscreen) {
Expand Down

0 comments on commit c0ff29d

Please sign in to comment.