Skip to content

Commit 37b7739

Browse files
committed
WIP implement own context classes
1 parent 8868e1e commit 37b7739

File tree

8 files changed

+774
-133
lines changed

8 files changed

+774
-133
lines changed

rendercanvas/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@
88
from . import _coreutils
99
from ._enums import CursorShape, EventType, UpdateMode
1010
from .base import BaseRenderCanvas, BaseLoop
11+
from . import contexts
12+
from . import utils
13+
1114

1215
__all__ = ["BaseLoop", "BaseRenderCanvas", "CursorShape", "EventType", "UpdateMode"]

rendercanvas/base.py

Lines changed: 71 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
CursorShape,
1616
CursorShapeEnum,
1717
)
18+
from . import contexts
1819
from ._events import EventEmitter
1920
from ._loop import BaseLoop
2021
from ._scheduler import Scheduler
@@ -238,12 +239,14 @@ def get_context(self, context_type: str) -> object:
238239
if not isinstance(context_type, str):
239240
raise TypeError("context_type must be str.")
240241

242+
present_method_map = context_type_map = {"screen": "wgpu"}
243+
241244
# Resolve the context type name
242-
known_types = {
243-
"wgpu": "wgpu",
244-
"bitmap": "rendercanvas.utils.bitmaprenderingcontext",
245-
}
246-
resolved_context_type = known_types.get(context_type, context_type)
245+
resolved_context_type = context_type_map.get(context_type, context_type)
246+
if resolved_context_type not in ("bitmap", "wgpu"):
247+
raise ValueError(
248+
"The given context type is invalid: {context_type!r} is not 'bitmap' or 'wgpu'."
249+
)
247250

248251
# Is the context already set?
249252
if self._canvas_context is not None:
@@ -254,34 +257,70 @@ def get_context(self, context_type: str) -> object:
254257
f"Cannot get context for '{context_type}': a context of type '{self._canvas_context._context_type}' is already set."
255258
)
256259

257-
# Load module
258-
module_name, _, class_name = resolved_context_type.partition(":")
259-
try:
260-
module = importlib.import_module(module_name)
261-
except ImportError as err:
262-
raise ValueError(
263-
f"Cannot get context for '{context_type}': {err}. Known valid values are {set(known_types)}"
264-
) from None
265-
266-
# Obtain factory to produce context
267-
factory_name = class_name or "rendercanvas_context_hook"
268-
try:
269-
factory_func = getattr(module, factory_name)
270-
except AttributeError:
271-
raise ValueError(
272-
f"Cannot get context for '{context_type}': could not find `{factory_name}` in '{module.__name__}'"
273-
) from None
274-
275-
# Create the context
276-
context = factory_func(self, self._rc_get_present_methods())
260+
# # Load module
261+
# module_name, _, class_name = resolved_context_type.partition(":")
262+
# try:
263+
# module = importlib.import_module(module_name)
264+
# except ImportError as err:
265+
# raise ValueError(
266+
# f"Cannot get context for '{context_type}': {err}. Known valid values are {set(known_types)}"
267+
# ) from None
268+
269+
# # Obtain factory to produce context
270+
# factory_name = class_name or "rendercanvas_context_hook"
271+
# try:
272+
# factory_func = getattr(module, factory_name)
273+
# except AttributeError:
274+
# raise ValueError(
275+
# f"Cannot get context for '{context_type}': could not find `{factory_name}` in '{module.__name__}'"
276+
# ) from None
277+
278+
# # Create the context
279+
# context = factory_func(self, self._rc_get_present_methods())
280+
281+
# # Quick checks to make sure the context has the correct API
282+
# if not (hasattr(context, "canvas") and context.canvas is self):
283+
# raise RuntimeError(
284+
# "The context does not have a canvas attribute that refers to this canvas."
285+
# )
286+
# if not (hasattr(context, "present") and callable(context.present)):
287+
# raise RuntimeError("The context does not have a present method.")
288+
289+
# Select present_method
290+
# todo: does the canvas present_method arg override this in the appropriate way?
291+
present_methods = self._rc_get_present_methods()
292+
present_method = None
293+
if resolved_context_type == "bitmap":
294+
for name in ("bitmap", "wgpu", "screen"):
295+
if name in present_methods:
296+
present_method = name
297+
break
298+
else:
299+
for name in ("wgpu", "screen", "bitmap"):
300+
if name in present_methods:
301+
present_method = name
302+
break
277303

278-
# Quick checks to make sure the context has the correct API
279-
if not (hasattr(context, "canvas") and context.canvas is self):
304+
# This should never happen, unless there's a bug
305+
if present_method is None:
280306
raise RuntimeError(
281-
"The context does not have a canvas attribute that refers to this canvas."
307+
"Could not select present_method for context_type {context_type!r} from present_methods {present_methods!r}"
282308
)
283-
if not (hasattr(context, "present") and callable(context.present)):
284-
raise RuntimeError("The context does not have a present method.")
309+
310+
# Select present_info
311+
present_info = dict(present_methods[present_method])
312+
assert "method" not in present_info, (
313+
"the field 'method' is reserved in present_methods dicts"
314+
)
315+
present_info = {
316+
"method": present_method_map.get(present_method, present_method),
317+
**present_info,
318+
}
319+
320+
if resolved_context_type == "bitmap":
321+
context = contexts.BitmapContext(self, present_info)
322+
else:
323+
context = contexts.WGpuContext(self, present_info)
285324

286325
# Done
287326
self._canvas_context = context
@@ -498,9 +537,9 @@ def _draw_frame_and_present(self):
498537
# Note: if vsync is used, this call may wait a little (happens down at the level of the driver or OS)
499538
context = self._canvas_context
500539
if context:
501-
result = context.present()
540+
result = context._rc_present()
502541
method = result.pop("method")
503-
if method in ("skip", "screen"):
542+
if method in ("skip", "screen", "delegated"):
504543
pass # nothing we need to do
505544
elif method == "fail":
506545
raise RuntimeError(result.get("message", "") or "present error")

rendercanvas/contexts/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .basecontext import BaseContext
2+
from .bitmapcontext import BitmapContext

0 commit comments

Comments
 (0)