From 85367ca1bb595ccf2cf15b8d5622407b473f534a Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Wed, 29 Feb 2012 19:38:32 +0100 Subject: [PATCH 1/6] core/graphics: use a gpu buffer for storing vertex indices, and use it with GL_ELEMENT_ARRAY_BUFFER. Faster for screen with lot of drawings. + dont unbind after drawing, but only when using Callback instruction. --- kivy/graphics/instructions.pyx | 11 +++++++---- kivy/graphics/vbo.pxd | 4 ++++ kivy/graphics/vbo.pyx | 35 ++++++++++++++++++++++++++++++---- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/kivy/graphics/instructions.pyx b/kivy/graphics/instructions.pyx index 77a09b1a8..e029d376e 100644 --- a/kivy/graphics/instructions.pyx +++ b/kivy/graphics/instructions.pyx @@ -291,7 +291,7 @@ cdef class VertexInstruction(Instruction): size: self.size .. note:: - + The filename will be searched with the :func:`kivy.resources.resource_find` function. @@ -342,7 +342,7 @@ cdef class VertexInstruction(Instruction): cdef class Callback(Instruction): '''.. versionadded:: 1.0.4 - + A Callback is an instruction that will be called when the drawing operation is performed. When adding instructions to a canvas, you can do this:: @@ -404,6 +404,9 @@ cdef class Callback(Instruction): cdef Shader shader cdef int i + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) + glBindBuffer(GL_ARRAY_BUFFER, 0) + if self.func(self): self.flag_update_done() @@ -547,7 +550,7 @@ cdef CanvasBase getActiveCanvas(): global ACTIVE_CANVAS return ACTIVE_CANVAS -# Canvas Stack, for internal use so canvas can be bound +# Canvas Stack, for internal use so canvas can be bound # inside other canvas, and restroed when other canvas is done cdef list CANVAS_STACK = list() @@ -561,7 +564,7 @@ cdef popActiveCanvas(): ACTIVE_CANVAS = CANVAS_STACK.pop() -#TODO: same as canvas, move back to context.pyx..fix circular import +#TODO: same as canvas, move back to context.pyx..fix circular import #on actual import from python problem include "common.pxi" from vertex cimport * diff --git a/kivy/graphics/vbo.pxd b/kivy/graphics/vbo.pxd index f5487f5a3..a1c9962bf 100644 --- a/kivy/graphics/vbo.pxd +++ b/kivy/graphics/vbo.pxd @@ -30,6 +30,10 @@ cdef class VertexBatch: cdef Buffer vbo_index cdef GLuint mode cdef str mode_str + cdef GLuint id + cdef int usage + cdef int elements_size + cdef int need_upload cdef void clear_data(self) cdef void set_data(self, vertex_t *vertices, int vertices_count, diff --git a/kivy/graphics/vbo.pyx b/kivy/graphics/vbo.pyx index 1125e66bb..e8d137f65 100644 --- a/kivy/graphics/vbo.pyx +++ b/kivy/graphics/vbo.pyx @@ -3,7 +3,7 @@ Vertex Buffer ============= The :class:`VBO` class handle the creation and update of Vertex Buffer Object in -OpenGL. +OpenGL. ''' __all__ = ('VBO', 'VertexBatch') @@ -106,16 +106,27 @@ cdef class VBO: cdef class VertexBatch: def __init__(self, **kwargs): + self.usage = GL_DYNAMIC_DRAW cdef object lushort = sizeof(unsigned short) self.vbo = kwargs.get('vbo') if self.vbo is None: self.vbo = VBO() self.vbo_index = Buffer(lushort) #index of every vertex in the vbo self.elements = Buffer(lushort) #indices translated to vbo indices + self.elements_size = 0 + self.need_upload = 1 + glGenBuffers(1, &self.id) self.set_data(NULL, 0, NULL, 0) self.set_mode(kwargs.get('mode')) + def __dealloc__(self): + # Add texture deletion outside GC call. + if _vbo_release_list is not None: + _vbo_release_list.append(self.id) + if _vbo_release_trigger is not None: + _vbo_release_trigger() + cdef void clear_data(self): # clear old vertices from vbo and then reset index buffer self.vbo.remove_vertex_data(self.vbo_index.pointer(), @@ -123,7 +134,6 @@ cdef class VertexBatch: self.vbo_index.clear() self.elements.clear() - cdef void set_data(self, vertex_t *vertices, int vertices_count, unsigned short *indices, int indices_count): #clear old vertices first @@ -132,6 +142,7 @@ cdef class VertexBatch: # now append the vertices and indices to vbo self.append_data(vertices, vertices_count, indices, indices_count) + self.need_upload = 1 cdef void append_data(self, vertex_t *vertices, int vertices_count, unsigned short *indices, int indices_count): @@ -151,12 +162,28 @@ cdef class VertexBatch: for i in xrange(indices_count): local_index = indices[i] self.elements.add(&vbi[local_index], NULL, 1) + self.need_upload = 1 cdef void draw(self): + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id) + # cache indices in a gpu buffer too + if self.need_upload: + if self.elements_size == self.elements.size(): + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, self.elements_size, + self.elements.pointer()) + else: + glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.elements.size(), + self.elements.pointer(), self.usage) + self.elements_size = self.elements.size() + self.need_upload = 0 self.vbo.bind() glDrawElements(self.mode, self.elements.count(), - GL_UNSIGNED_SHORT, self.elements.pointer()) - self.vbo.unbind() + GL_UNSIGNED_SHORT, NULL) + + # XXX if the user is doing its own things, Callback instruction will + # reset the context. + # self.vbo.unbind() + # glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) cdef void set_mode(self, str mode): # most common case in top; From 732f239b54263652fd1a311936d50b5c9b4733ed Mon Sep 17 00:00:00 2001 From: Qua-non Date: Thu, 1 Mar 2012 01:58:57 +0530 Subject: [PATCH 2/6] propagate on_touch_down to kids in Button and Label --- kivy/uix/button.py | 2 ++ kivy/uix/label.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/kivy/uix/button.py b/kivy/uix/button.py index 1a527305e..cb782c748 100644 --- a/kivy/uix/button.py +++ b/kivy/uix/button.py @@ -111,6 +111,8 @@ class Button(Label): self.state = 'normal' def on_touch_down(self, touch): + if super(Button, self).on_touch_down(touch): + return True if not self.collide_point(touch.x, touch.y): return False if self in touch.ud: diff --git a/kivy/uix/label.py b/kivy/uix/label.py index 2d3b9a937..c752dd7ae 100644 --- a/kivy/uix/label.py +++ b/kivy/uix/label.py @@ -179,6 +179,8 @@ class Label(Widget): self.texture_size = list(self.texture.size) def on_touch_down(self, touch): + if super(Label, self).on_touch_down(touch): + return True if not len(self.refs): return False tx, ty = touch.pos From e2cf603ddd5b996e3eb03e182ed3e708467f4341 Mon Sep 17 00:00:00 2001 From: Qua-non Date: Thu, 1 Mar 2012 11:50:48 +0530 Subject: [PATCH 3/6] propagate touch_move and touch_up events to kids and two style guide fixes --- kivy/uix/button.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kivy/uix/button.py b/kivy/uix/button.py index cb782c748..ce4f217e6 100644 --- a/kivy/uix/button.py +++ b/kivy/uix/button.py @@ -67,7 +67,8 @@ class Button(Label): default to [1, 1, 1, 1]. ''' - background_normal = StringProperty('atlas://data/images/defaulttheme/button') + background_normal = StringProperty( + 'atlas://data/images/defaulttheme/button') '''Background image of the button used for default graphical representation, when the button is not pressed. @@ -77,7 +78,8 @@ class Button(Label): default to 'atlas://data/images/defaulttheme/button' ''' - background_down = StringProperty('atlas://data/images/defaulttheme/button_pressed') + background_down = StringProperty( + 'atlas://data/images/defaulttheme/button_pressed') '''Background image of the button used for default graphical representation, when the button is pressed. @@ -124,9 +126,13 @@ class Button(Label): return True def on_touch_move(self, touch): + if super(Button, self).on_touch_move(touch): + return True return self in touch.ud def on_touch_up(self, touch): + if super(Button, self).on_touch_up(touch): + return True if touch.grab_current is not self: return assert(self in touch.ud) From 62752ddd2669df3a00bf54de4f3d5ad6836647eb Mon Sep 17 00:00:00 2001 From: Qua-non Date: Fri, 2 Mar 2012 03:01:00 +0530 Subject: [PATCH 4/6] Remove redundant `background_texture`, this also fixes updation of texture when background_image was changed. --- kivy/data/style.kv | 2 +- kivy/uix/bubble.py | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/kivy/data/style.kv b/kivy/data/style.kv index 86742f3b5..0c5920ad0 100644 --- a/kivy/data/style.kv +++ b/kivy/data/style.kv @@ -33,7 +33,7 @@ rgba: self.parent.background_color if self.parent else (1, 1, 1, 1) BorderImage: border: self.parent.border if self.parent else (16, 16, 16, 16) - texture: root.parent.background_texture if root.parent else None + texture: root.parent._bk_img.texture if root.parent else None size: self.size pos: self.pos diff --git a/kivy/uix/bubble.py b/kivy/uix/bubble.py index 519281152..71934751c 100644 --- a/kivy/uix/bubble.py +++ b/kivy/uix/bubble.py @@ -131,13 +131,6 @@ class Bubble(GridLayout): default to 'bottom_mid'. ''' - background_texture = ObjectProperty(None) - '''Specifies the background texture of the bubble - - :data:`background_texture` is a :class:`~kivy.properties.ObjectProperty`, - default to 'None'. - ''' - content = ObjectProperty(None) '''This is the object where the main content of the bubble is held @@ -165,12 +158,8 @@ class Bubble(GridLayout): self.content = content = BubbleContent(parent=self) super(Bubble, self).__init__(**kwargs) self.add_widget(content) - self._bk_img.bind(on_texture=self._on_texture) self.on_arrow_pos() - def _on_texture(self, *l): - self.background_texture = self._bk_img.texture - def add_widget(self, *l): content = self.content if content is None: From 6c1430d3c2715fef81ea5ab8dd6ede057bdce7fe Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Thu, 1 Mar 2012 23:45:19 +0100 Subject: [PATCH 5/6] button: fix grabbing priority in touch move/up --- kivy/uix/button.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kivy/uix/button.py b/kivy/uix/button.py index ce4f217e6..781240176 100644 --- a/kivy/uix/button.py +++ b/kivy/uix/button.py @@ -126,15 +126,15 @@ class Button(Label): return True def on_touch_move(self, touch): + if touch.grab_current is self: + return True if super(Button, self).on_touch_move(touch): return True return self in touch.ud def on_touch_up(self, touch): - if super(Button, self).on_touch_up(touch): - return True if touch.grab_current is not self: - return + return super(Button, self).on_touch_up(touch) assert(self in touch.ud) touch.ungrab(self) self._do_release() From 4952db3b2293c648011e5ada18a5f49fade7926e Mon Sep 17 00:00:00 2001 From: Mathieu Virbel Date: Fri, 2 Mar 2012 00:48:32 +0100 Subject: [PATCH 6/6] core/window: implement a new dropfile event, currently used only on macosx. --- kivy/core/window/__init__.py | 16 ++++++++++++++++ kivy/core/window/window_pygame.py | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/kivy/core/window/__init__.py b/kivy/core/window/__init__.py index 811be299c..45b59648f 100755 --- a/kivy/core/window/__init__.py +++ b/kivy/core/window/__init__.py @@ -195,6 +195,8 @@ class WindowBase(EventDispatcher): Fired when a key is down `on_key_up`: key, scancode, unicode Fired when a key is up + `on_dropfile`: str + Fired when a file is dropped on the application ''' __instance = None @@ -367,6 +369,7 @@ class WindowBase(EventDispatcher): self.register_event_type('on_keyboard') self.register_event_type('on_key_down') self.register_event_type('on_key_up') + self.register_event_type('on_dropfile') super(WindowBase, self).__init__() @@ -711,6 +714,19 @@ class WindowBase(EventDispatcher): '''Event called when a key is up (same arguments as on_keyboard)''' pass + def on_dropfile(self, filename): + '''Event called when a file is dropped on the application. + + .. warning:: + + This event is actually used only on MacOSX with a patched version of + pygame. But this will be a place for a further evolution (ios, + android etc.) + + .. versionadded:: 1.1.2 + ''' + pass + def configure_keyboards(self): # Configure how to provide keyboards (virtual or not) diff --git a/kivy/core/window/window_pygame.py b/kivy/core/window/window_pygame.py index cea54b3da..bf135782d 100644 --- a/kivy/core/window/window_pygame.py +++ b/kivy/core/window/window_pygame.py @@ -273,6 +273,11 @@ class WindowPygame(WindowBase): elif event.type == pygame.ACTIVEEVENT: pass + # drop file (pygame patch needed) + elif event.type == pygame.USEREVENT and hasattr(pygame, + 'USEREVENT_DROPFILE') and event.code == pygame.USEREVENT_DROPFILE: + self.dispatch('on_dropfile', event.filename) + ''' # unhandled event ! else: