| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 6 #error "This file requires ARC support." | |
| 7 #endif | |
| 8 | |
| 9 #import "remoting/ios/ui/cursor_texture.h" | |
| 10 | |
| 11 @implementation CursorTexture | |
| 12 | |
| 13 - (id)init { | |
| 14 self = [super init]; | |
| 15 if (self) { | |
| 16 _needCursorRedraw = NO; | |
| 17 _cursorDrawnToGL = webrtc::DesktopRect::MakeXYWH(0, 0, 0, 0); | |
| 18 } | |
| 19 return self; | |
| 20 } | |
| 21 | |
| 22 - (const webrtc::DesktopSize&)textureSize { | |
| 23 return _textureSize; | |
| 24 } | |
| 25 | |
| 26 - (void)setTextureSize:(const webrtc::DesktopSize&)size { | |
| 27 if (!_textureSize.equals(size)) { | |
| 28 _textureSize.set(size.width(), size.height()); | |
| 29 _needInitialize = true; | |
| 30 } | |
| 31 } | |
| 32 | |
| 33 - (const webrtc::MouseCursor&)cursor { | |
| 34 return *_cursor.get(); | |
| 35 } | |
| 36 | |
| 37 - (void)setCursor:(webrtc::MouseCursor*)cursor { | |
| 38 _cursor.reset(cursor); | |
| 39 | |
| 40 if (_cursor.get() != NULL && _cursor->image().data()) { | |
| 41 _needCursorRedraw = true; | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 - (void)bindToEffect:(GLKEffectPropertyTexture*)effectProperty { | |
| 46 glGenTextures(1, &_textureId); | |
| 47 [Utility bindTextureForIOS:_textureId]; | |
| 48 | |
| 49 // This is the Cursor layer, and is stamped on top of Desktop as a | |
| 50 // transparent image | |
| 51 effectProperty.target = GLKTextureTarget2D; | |
| 52 effectProperty.name = _textureId; | |
| 53 effectProperty.envMode = GLKTextureEnvModeDecal; | |
| 54 effectProperty.enabled = GL_TRUE; | |
| 55 | |
| 56 [Utility logGLErrorCode:@"CursorTexture bindToTexture"]; | |
| 57 // Release context | |
| 58 glBindTexture(GL_TEXTURE_2D, 0); | |
| 59 } | |
| 60 | |
| 61 - (BOOL)needDrawAtPosition:(const webrtc::DesktopVector&)position { | |
| 62 return (_cursor.get() != NULL && | |
| 63 (_needInitialize || _needCursorRedraw == YES || | |
| 64 _cursorDrawnToGL.left() != position.x() - _cursor->hotspot().x() || | |
| 65 _cursorDrawnToGL.top() != position.y() - _cursor->hotspot().y())); | |
| 66 } | |
| 67 | |
| 68 - (void)drawWithMousePosition:(const webrtc::DesktopVector&)position { | |
| 69 if (_textureSize.height() == 0 && _textureSize.width() == 0) { | |
| 70 return; | |
| 71 } | |
| 72 | |
| 73 [Utility bindTextureForIOS:_textureId]; | |
| 74 | |
| 75 if (_needInitialize) { | |
| 76 glTexImage2D(GL_TEXTURE_2D, | |
| 77 0, | |
| 78 GL_RGBA, | |
| 79 _textureSize.width(), | |
| 80 _textureSize.height(), | |
| 81 0, | |
| 82 GL_RGBA, | |
| 83 GL_UNSIGNED_BYTE, | |
| 84 NULL); | |
| 85 | |
| 86 [Utility logGLErrorCode:@"CursorTexture initializeTextureSurfaceWithSize"]; | |
| 87 _needInitialize = false; | |
| 88 } | |
| 89 // When the cursor needs to be redraw in a different spot then we must clear | |
| 90 // the previous area. | |
| 91 | |
| 92 DCHECK([self needDrawAtPosition:position]); | |
| 93 | |
| 94 if (_cursorDrawnToGL.width() > 0 && _cursorDrawnToGL.height() > 0) { | |
| 95 webrtc::BasicDesktopFrame transparentCursor(_cursorDrawnToGL.size()); | |
| 96 | |
| 97 if (transparentCursor.data() != NULL) { | |
| 98 DCHECK(transparentCursor.kBytesPerPixel == | |
| 99 _cursor->image().kBytesPerPixel); | |
| 100 memset(transparentCursor.data(), | |
| 101 0, | |
| 102 transparentCursor.stride() * transparentCursor.size().height()); | |
| 103 | |
| 104 [Utility drawSubRectToGLFromRectOfSize:_textureSize | |
| 105 subRect:_cursorDrawnToGL | |
| 106 data:transparentCursor.data()]; | |
| 107 | |
| 108 // there is no longer any cursor drawn to screen | |
| 109 _cursorDrawnToGL = webrtc::DesktopRect::MakeXYWH(0, 0, 0, 0); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 if (_cursor.get() != NULL) { | |
| 114 | |
| 115 CGRect screen = | |
| 116 CGRectMake(0.0, 0.0, _textureSize.width(), _textureSize.height()); | |
| 117 CGRect cursor = CGRectMake(position.x() - _cursor->hotspot().x(), | |
| 118 position.y() - _cursor->hotspot().y(), | |
| 119 _cursor->image().size().width(), | |
| 120 _cursor->image().size().height()); | |
| 121 | |
| 122 if (CGRectContainsRect(screen, cursor)) { | |
| 123 _cursorDrawnToGL = webrtc::DesktopRect::MakeXYWH(cursor.origin.x, | |
| 124 cursor.origin.y, | |
| 125 cursor.size.width, | |
| 126 cursor.size.height); | |
| 127 | |
| 128 [Utility drawSubRectToGLFromRectOfSize:_textureSize | |
| 129 subRect:_cursorDrawnToGL | |
| 130 data:_cursor->image().data()]; | |
| 131 | |
| 132 } else if (CGRectIntersectsRect(screen, cursor)) { | |
| 133 // Some of the cursor falls off screen, need to clip it | |
| 134 CGRect intersection = CGRectIntersection(screen, cursor); | |
| 135 _cursorDrawnToGL = | |
| 136 webrtc::DesktopRect::MakeXYWH(intersection.origin.x, | |
| 137 intersection.origin.y, | |
| 138 intersection.size.width, | |
| 139 intersection.size.height); | |
| 140 | |
| 141 webrtc::BasicDesktopFrame partialCursor(_cursorDrawnToGL.size()); | |
| 142 | |
| 143 if (partialCursor.data()) { | |
| 144 DCHECK(partialCursor.kBytesPerPixel == _cursor->image().kBytesPerPixel); | |
| 145 | |
| 146 uint32_t src_stride = _cursor->image().stride(); | |
| 147 uint32_t dst_stride = partialCursor.stride(); | |
| 148 | |
| 149 uint8_t* source = _cursor->image().data(); | |
| 150 source += abs((static_cast<int32_t>(cursor.origin.y) - | |
| 151 _cursorDrawnToGL.top())) * | |
| 152 src_stride; | |
| 153 source += abs((static_cast<int32_t>(cursor.origin.x) - | |
| 154 _cursorDrawnToGL.left())) * | |
| 155 _cursor->image().kBytesPerPixel; | |
| 156 uint8_t* dst = partialCursor.data(); | |
| 157 | |
| 158 for (uint32_t y = 0; y < _cursorDrawnToGL.height(); y++) { | |
| 159 memcpy(dst, source, dst_stride); | |
| 160 source += src_stride; | |
| 161 dst += dst_stride; | |
| 162 } | |
| 163 | |
| 164 [Utility drawSubRectToGLFromRectOfSize:_textureSize | |
| 165 subRect:_cursorDrawnToGL | |
| 166 data:partialCursor.data()]; | |
| 167 } | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 _needCursorRedraw = false; | |
| 172 [Utility logGLErrorCode:@"CursorTexture drawWithMousePosition"]; | |
| 173 // Release context | |
| 174 glBindTexture(GL_TEXTURE_2D, 0); | |
| 175 } | |
| 176 | |
| 177 - (void)releaseTexture { | |
| 178 glDeleteTextures(1, &_textureId); | |
| 179 } | |
| 180 | |
| 181 @end | |
| OLD | NEW |