// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "webkit/glue/plugins/mac_accelerated_surface_container.h" #include "app/surface/io_surface_support_mac.h" #include "base/logging.h" #include "webkit/glue/plugins/mac_accelerated_surface_container_manager.h" #include "webkit/glue/plugins/webplugin.h" MacAcceleratedSurfaceContainer::MacAcceleratedSurfaceContainer() : x_(0), y_(0), surface_(NULL), width_(0), height_(0), texture_(0) { } MacAcceleratedSurfaceContainer::~MacAcceleratedSurfaceContainer() { ReleaseIOSurface(); } void MacAcceleratedSurfaceContainer::ReleaseIOSurface() { if (surface_) { CFRelease(surface_); surface_ = NULL; } } void MacAcceleratedSurfaceContainer::SetSizeAndIOSurface( int32 width, int32 height, uint64 io_surface_identifier, MacAcceleratedSurfaceContainerManager* manager) { ReleaseIOSurface(); IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); if (io_surface_support) { surface_ = io_surface_support->IOSurfaceLookup( static_cast(io_surface_identifier)); EnqueueTextureForDeletion(manager); width_ = width; height_ = height; } } void MacAcceleratedSurfaceContainer::SetSizeAndTransportDIB( int32 width, int32 height, TransportDIB::Handle transport_dib, MacAcceleratedSurfaceContainerManager* manager) { if (TransportDIB::is_valid(transport_dib)) { transport_dib_.reset(TransportDIB::Map(transport_dib)); EnqueueTextureForDeletion(manager); width_ = width; height_ = height; } } void MacAcceleratedSurfaceContainer::MoveTo( const webkit_glue::WebPluginGeometry& geom) { x_ = geom.window_rect.x(); y_ = geom.window_rect.y(); // TODO(kbr): may need to pay attention to cutout rects. clipRect_ = geom.clip_rect; } void MacAcceleratedSurfaceContainer::Draw(CGLContextObj context) { IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); GLenum target = GL_TEXTURE_RECTANGLE_ARB; if (!texture_) { if ((io_surface_support && !surface_) || (!io_surface_support && !transport_dib_.get())) return; glGenTextures(1, &texture_); glBindTexture(target, texture_); glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // When using an IOSurface, the texture does not need to be repeatedly // uploaded, so bind the IOSurface once during texture gen in this case. if (io_surface_support) { DCHECK(surface_); // Don't think we need to identify a plane. GLuint plane = 0; io_surface_support->CGLTexImageIOSurface2D(context, target, GL_RGBA, width_, height_, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface_, plane); } else { // Reserve space on the card for the actual texture upload, done with the // glTexSubImage2D() call, below. glTexImage2D(target, 0, // mipmap level 0 GL_RGBA, // internal format width_, height_, 0, // no border GL_BGRA, // The GPU plugin read BGRA pixels GL_UNSIGNED_INT_8_8_8_8_REV, NULL); // No data, this call just reserves room. } } // If using TransportDIBs, the texture needs to be uploaded every frame. if (transport_dib_.get() != NULL) { void* pixel_memory = transport_dib_->memory(); if (pixel_memory) { glBindTexture(target, texture_); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Needed for NPOT textures. glTexSubImage2D(target, 0, // mipmap level 0 0, // x-offset 0, // y-offset width_, height_, GL_BGRA, // The GPU plugin gave us BGRA pixels GL_UNSIGNED_INT_8_8_8_8_REV, pixel_memory); } } if (texture_) { // TODO(kbr): convert this to use only OpenGL ES 2.0 functionality glBindTexture(target, texture_); glEnable(target); glBegin(GL_TRIANGLE_STRIP); // TODO(kbr): may need to pay attention to cutout rects. int clipX = clipRect_.x(); int clipY = clipRect_.y(); int clipWidth = clipRect_.width(); int clipHeight = clipRect_.height(); int x = x_ + clipX; int y = y_ + clipY; glTexCoord2f(clipX, height_ - clipY); glVertex3f(x, y, 0); glTexCoord2f(clipX + clipWidth, height_ - clipY); glVertex3f(x + clipWidth, y, 0); glTexCoord2f(clipX, height_ - clipY - clipHeight); glVertex3f(x, y + clipHeight, 0); glTexCoord2f(clipX + clipWidth, height_ - clipY - clipHeight); glVertex3f(x + clipWidth, y + clipHeight, 0); glEnd(); glDisable(target); } } void MacAcceleratedSurfaceContainer::EnqueueTextureForDeletion( MacAcceleratedSurfaceContainerManager* manager) { manager->EnqueueTextureForDeletion(texture_); texture_ = 0; }