| Index: remoting/ios/ui/cursor_texture.mm
|
| diff --git a/remoting/ios/ui/cursor_texture.mm b/remoting/ios/ui/cursor_texture.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9ffa5f7f12208e55cd4b579b70ef85a695e92837
|
| --- /dev/null
|
| +++ b/remoting/ios/ui/cursor_texture.mm
|
| @@ -0,0 +1,181 @@
|
| +// Copyright 2014 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.
|
| +
|
| +#if !defined(__has_feature) || !__has_feature(objc_arc)
|
| +#error "This file requires ARC support."
|
| +#endif
|
| +
|
| +#import "remoting/ios/ui/cursor_texture.h"
|
| +
|
| +@implementation CursorTexture
|
| +
|
| +- (id)init {
|
| + self = [super init];
|
| + if (self) {
|
| + _needCursorRedraw = NO;
|
| + _cursorDrawnToGL = webrtc::DesktopRect::MakeXYWH(0, 0, 0, 0);
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (const webrtc::DesktopSize&)textureSize {
|
| + return _textureSize;
|
| +}
|
| +
|
| +- (void)setTextureSize:(const webrtc::DesktopSize&)size {
|
| + if (!_textureSize.equals(size)) {
|
| + _textureSize.set(size.width(), size.height());
|
| + _needInitialize = true;
|
| + }
|
| +}
|
| +
|
| +- (const webrtc::MouseCursor&)cursor {
|
| + return *_cursor.get();
|
| +}
|
| +
|
| +- (void)setCursor:(webrtc::MouseCursor*)cursor {
|
| + _cursor.reset(cursor);
|
| +
|
| + if (_cursor.get() != NULL && _cursor->image().data()) {
|
| + _needCursorRedraw = true;
|
| + }
|
| +}
|
| +
|
| +- (void)bindToEffect:(GLKEffectPropertyTexture*)effectProperty {
|
| + glGenTextures(1, &_textureId);
|
| + [Utility bindTextureForIOS:_textureId];
|
| +
|
| + // This is the Cursor layer, and is stamped on top of Desktop as a
|
| + // transparent image
|
| + effectProperty.target = GLKTextureTarget2D;
|
| + effectProperty.name = _textureId;
|
| + effectProperty.envMode = GLKTextureEnvModeDecal;
|
| + effectProperty.enabled = GL_TRUE;
|
| +
|
| + [Utility logGLErrorCode:@"CursorTexture bindToTexture"];
|
| + // Release context
|
| + glBindTexture(GL_TEXTURE_2D, 0);
|
| +}
|
| +
|
| +- (BOOL)needDrawAtPosition:(const webrtc::DesktopVector&)position {
|
| + return (_cursor.get() != NULL &&
|
| + (_needInitialize || _needCursorRedraw == YES ||
|
| + _cursorDrawnToGL.left() != position.x() - _cursor->hotspot().x() ||
|
| + _cursorDrawnToGL.top() != position.y() - _cursor->hotspot().y()));
|
| +}
|
| +
|
| +- (void)drawWithMousePosition:(const webrtc::DesktopVector&)position {
|
| + if (_textureSize.height() == 0 && _textureSize.width() == 0) {
|
| + return;
|
| + }
|
| +
|
| + [Utility bindTextureForIOS:_textureId];
|
| +
|
| + if (_needInitialize) {
|
| + glTexImage2D(GL_TEXTURE_2D,
|
| + 0,
|
| + GL_RGBA,
|
| + _textureSize.width(),
|
| + _textureSize.height(),
|
| + 0,
|
| + GL_RGBA,
|
| + GL_UNSIGNED_BYTE,
|
| + NULL);
|
| +
|
| + [Utility logGLErrorCode:@"CursorTexture initializeTextureSurfaceWithSize"];
|
| + _needInitialize = false;
|
| + }
|
| + // When the cursor needs to be redraw in a different spot then we must clear
|
| + // the previous area.
|
| +
|
| + DCHECK([self needDrawAtPosition:position]);
|
| +
|
| + if (_cursorDrawnToGL.width() > 0 && _cursorDrawnToGL.height() > 0) {
|
| + webrtc::BasicDesktopFrame transparentCursor(_cursorDrawnToGL.size());
|
| +
|
| + if (transparentCursor.data() != NULL) {
|
| + DCHECK(transparentCursor.kBytesPerPixel ==
|
| + _cursor->image().kBytesPerPixel);
|
| + memset(transparentCursor.data(),
|
| + 0,
|
| + transparentCursor.stride() * transparentCursor.size().height());
|
| +
|
| + [Utility drawSubRectToGLFromRectOfSize:_textureSize
|
| + subRect:_cursorDrawnToGL
|
| + data:transparentCursor.data()];
|
| +
|
| + // there is no longer any cursor drawn to screen
|
| + _cursorDrawnToGL = webrtc::DesktopRect::MakeXYWH(0, 0, 0, 0);
|
| + }
|
| + }
|
| +
|
| + if (_cursor.get() != NULL) {
|
| +
|
| + CGRect screen =
|
| + CGRectMake(0.0, 0.0, _textureSize.width(), _textureSize.height());
|
| + CGRect cursor = CGRectMake(position.x() - _cursor->hotspot().x(),
|
| + position.y() - _cursor->hotspot().y(),
|
| + _cursor->image().size().width(),
|
| + _cursor->image().size().height());
|
| +
|
| + if (CGRectContainsRect(screen, cursor)) {
|
| + _cursorDrawnToGL = webrtc::DesktopRect::MakeXYWH(cursor.origin.x,
|
| + cursor.origin.y,
|
| + cursor.size.width,
|
| + cursor.size.height);
|
| +
|
| + [Utility drawSubRectToGLFromRectOfSize:_textureSize
|
| + subRect:_cursorDrawnToGL
|
| + data:_cursor->image().data()];
|
| +
|
| + } else if (CGRectIntersectsRect(screen, cursor)) {
|
| + // Some of the cursor falls off screen, need to clip it
|
| + CGRect intersection = CGRectIntersection(screen, cursor);
|
| + _cursorDrawnToGL =
|
| + webrtc::DesktopRect::MakeXYWH(intersection.origin.x,
|
| + intersection.origin.y,
|
| + intersection.size.width,
|
| + intersection.size.height);
|
| +
|
| + webrtc::BasicDesktopFrame partialCursor(_cursorDrawnToGL.size());
|
| +
|
| + if (partialCursor.data()) {
|
| + DCHECK(partialCursor.kBytesPerPixel == _cursor->image().kBytesPerPixel);
|
| +
|
| + uint32_t src_stride = _cursor->image().stride();
|
| + uint32_t dst_stride = partialCursor.stride();
|
| +
|
| + uint8_t* source = _cursor->image().data();
|
| + source += abs((static_cast<int32_t>(cursor.origin.y) -
|
| + _cursorDrawnToGL.top())) *
|
| + src_stride;
|
| + source += abs((static_cast<int32_t>(cursor.origin.x) -
|
| + _cursorDrawnToGL.left())) *
|
| + _cursor->image().kBytesPerPixel;
|
| + uint8_t* dst = partialCursor.data();
|
| +
|
| + for (uint32_t y = 0; y < _cursorDrawnToGL.height(); y++) {
|
| + memcpy(dst, source, dst_stride);
|
| + source += src_stride;
|
| + dst += dst_stride;
|
| + }
|
| +
|
| + [Utility drawSubRectToGLFromRectOfSize:_textureSize
|
| + subRect:_cursorDrawnToGL
|
| + data:partialCursor.data()];
|
| + }
|
| + }
|
| + }
|
| +
|
| + _needCursorRedraw = false;
|
| + [Utility logGLErrorCode:@"CursorTexture drawWithMousePosition"];
|
| + // Release context
|
| + glBindTexture(GL_TEXTURE_2D, 0);
|
| +}
|
| +
|
| +- (void)releaseTexture {
|
| + glDeleteTextures(1, &_textureId);
|
| +}
|
| +
|
| +@end
|
|
|