Efficiency of querying an SDL_Surface for pixel colors
I'm writing a game that has a simple 2D map and needs to determine which "region" on the map the user clicked. Each region has a unique RGB color associated with it. So, given the (x,y)
coordinates of a click, I do this:
Uint32 *pixels = (Uint32 *) image_surface_->pixels;
Uint32 pixel = pixels[(y * image_surface_->w) + x];
Uint8 r, g, b;
SDL_GetRGB(pixel, image_surface_->format, &r, &g, &b);
SDL_Color rgb = {r, g, b, 255};
where image_surface_
is the SDL_Surface
which contains the map that was loaded into the game's SDL_Window
.
After the bit of code above, I run through the list of regions and check which of them has a matching color value.
My question is, what is the efficiency of querying an SDL_Surface
's pixels? Is it just O(1)
as appears to be the case because all you're doing is indexing a pointer? Or is there more going on?
(For the actual game I'm writing, poor efficiency doesn't matter much, but I plan on developing a mini-engine for the writing of 2D (and potentially, 3D games) that use a map, which could theoretically be very large with many regions)
c++ performance sdl sdl-2
|
show 5 more comments
I'm writing a game that has a simple 2D map and needs to determine which "region" on the map the user clicked. Each region has a unique RGB color associated with it. So, given the (x,y)
coordinates of a click, I do this:
Uint32 *pixels = (Uint32 *) image_surface_->pixels;
Uint32 pixel = pixels[(y * image_surface_->w) + x];
Uint8 r, g, b;
SDL_GetRGB(pixel, image_surface_->format, &r, &g, &b);
SDL_Color rgb = {r, g, b, 255};
where image_surface_
is the SDL_Surface
which contains the map that was loaded into the game's SDL_Window
.
After the bit of code above, I run through the list of regions and check which of them has a matching color value.
My question is, what is the efficiency of querying an SDL_Surface
's pixels? Is it just O(1)
as appears to be the case because all you're doing is indexing a pointer? Or is there more going on?
(For the actual game I'm writing, poor efficiency doesn't matter much, but I plan on developing a mini-engine for the writing of 2D (and potentially, 3D games) that use a map, which could theoretically be very large with many regions)
c++ performance sdl sdl-2
2
It is indeed O(1) but I wouldn't be using functions lie SDL_GetRGB if you can avoid it. Per pixel inner loop stuff is best done without calling a function or needing an if statement (ie branching). You can make the "pixel" pointer uint8_t* so that you can address the individual rgb components like pixel[RED_OFFSET], pixel[BLUE_OFFSET] for example.
– fret
Nov 13 '18 at 3:35
@fret What is the reason I should avoid calling a function?
– ubadub
Nov 13 '18 at 4:58
1
@ubadub function call is not free, and said function have a branch inside it. If target CPU don't have branch prediction - that will not be great to call it too many times in a loop (e.g. iterating through entire image). Not terrible, but you can do better without extra function call or braches.
– keltar
Nov 13 '18 at 8:59
1
@keltar never mind, I got it. Leaving it here for anyone else who needs it:(pixel & image_surface_->format->Rmask) >> image_surface_->format->Rshift;
– ubadub
Nov 14 '18 at 16:43
1
Also, this code is wrong. You should always usesurface->pitch
instead of width for calculating which row you are on. Even then this of course will be broken if you ever need to use it for a non 32 bit surface. Another reason to just do it the right way so you aren't needlessly shackled to specific formats.
– Brad Allred
Nov 15 '18 at 23:23
|
show 5 more comments
I'm writing a game that has a simple 2D map and needs to determine which "region" on the map the user clicked. Each region has a unique RGB color associated with it. So, given the (x,y)
coordinates of a click, I do this:
Uint32 *pixels = (Uint32 *) image_surface_->pixels;
Uint32 pixel = pixels[(y * image_surface_->w) + x];
Uint8 r, g, b;
SDL_GetRGB(pixel, image_surface_->format, &r, &g, &b);
SDL_Color rgb = {r, g, b, 255};
where image_surface_
is the SDL_Surface
which contains the map that was loaded into the game's SDL_Window
.
After the bit of code above, I run through the list of regions and check which of them has a matching color value.
My question is, what is the efficiency of querying an SDL_Surface
's pixels? Is it just O(1)
as appears to be the case because all you're doing is indexing a pointer? Or is there more going on?
(For the actual game I'm writing, poor efficiency doesn't matter much, but I plan on developing a mini-engine for the writing of 2D (and potentially, 3D games) that use a map, which could theoretically be very large with many regions)
c++ performance sdl sdl-2
I'm writing a game that has a simple 2D map and needs to determine which "region" on the map the user clicked. Each region has a unique RGB color associated with it. So, given the (x,y)
coordinates of a click, I do this:
Uint32 *pixels = (Uint32 *) image_surface_->pixels;
Uint32 pixel = pixels[(y * image_surface_->w) + x];
Uint8 r, g, b;
SDL_GetRGB(pixel, image_surface_->format, &r, &g, &b);
SDL_Color rgb = {r, g, b, 255};
where image_surface_
is the SDL_Surface
which contains the map that was loaded into the game's SDL_Window
.
After the bit of code above, I run through the list of regions and check which of them has a matching color value.
My question is, what is the efficiency of querying an SDL_Surface
's pixels? Is it just O(1)
as appears to be the case because all you're doing is indexing a pointer? Or is there more going on?
(For the actual game I'm writing, poor efficiency doesn't matter much, but I plan on developing a mini-engine for the writing of 2D (and potentially, 3D games) that use a map, which could theoretically be very large with many regions)
c++ performance sdl sdl-2
c++ performance sdl sdl-2
asked Nov 13 '18 at 3:25
ubadub
1,990821
1,990821
2
It is indeed O(1) but I wouldn't be using functions lie SDL_GetRGB if you can avoid it. Per pixel inner loop stuff is best done without calling a function or needing an if statement (ie branching). You can make the "pixel" pointer uint8_t* so that you can address the individual rgb components like pixel[RED_OFFSET], pixel[BLUE_OFFSET] for example.
– fret
Nov 13 '18 at 3:35
@fret What is the reason I should avoid calling a function?
– ubadub
Nov 13 '18 at 4:58
1
@ubadub function call is not free, and said function have a branch inside it. If target CPU don't have branch prediction - that will not be great to call it too many times in a loop (e.g. iterating through entire image). Not terrible, but you can do better without extra function call or braches.
– keltar
Nov 13 '18 at 8:59
1
@keltar never mind, I got it. Leaving it here for anyone else who needs it:(pixel & image_surface_->format->Rmask) >> image_surface_->format->Rshift;
– ubadub
Nov 14 '18 at 16:43
1
Also, this code is wrong. You should always usesurface->pitch
instead of width for calculating which row you are on. Even then this of course will be broken if you ever need to use it for a non 32 bit surface. Another reason to just do it the right way so you aren't needlessly shackled to specific formats.
– Brad Allred
Nov 15 '18 at 23:23
|
show 5 more comments
2
It is indeed O(1) but I wouldn't be using functions lie SDL_GetRGB if you can avoid it. Per pixel inner loop stuff is best done without calling a function or needing an if statement (ie branching). You can make the "pixel" pointer uint8_t* so that you can address the individual rgb components like pixel[RED_OFFSET], pixel[BLUE_OFFSET] for example.
– fret
Nov 13 '18 at 3:35
@fret What is the reason I should avoid calling a function?
– ubadub
Nov 13 '18 at 4:58
1
@ubadub function call is not free, and said function have a branch inside it. If target CPU don't have branch prediction - that will not be great to call it too many times in a loop (e.g. iterating through entire image). Not terrible, but you can do better without extra function call or braches.
– keltar
Nov 13 '18 at 8:59
1
@keltar never mind, I got it. Leaving it here for anyone else who needs it:(pixel & image_surface_->format->Rmask) >> image_surface_->format->Rshift;
– ubadub
Nov 14 '18 at 16:43
1
Also, this code is wrong. You should always usesurface->pitch
instead of width for calculating which row you are on. Even then this of course will be broken if you ever need to use it for a non 32 bit surface. Another reason to just do it the right way so you aren't needlessly shackled to specific formats.
– Brad Allred
Nov 15 '18 at 23:23
2
2
It is indeed O(1) but I wouldn't be using functions lie SDL_GetRGB if you can avoid it. Per pixel inner loop stuff is best done without calling a function or needing an if statement (ie branching). You can make the "pixel" pointer uint8_t* so that you can address the individual rgb components like pixel[RED_OFFSET], pixel[BLUE_OFFSET] for example.
– fret
Nov 13 '18 at 3:35
It is indeed O(1) but I wouldn't be using functions lie SDL_GetRGB if you can avoid it. Per pixel inner loop stuff is best done without calling a function or needing an if statement (ie branching). You can make the "pixel" pointer uint8_t* so that you can address the individual rgb components like pixel[RED_OFFSET], pixel[BLUE_OFFSET] for example.
– fret
Nov 13 '18 at 3:35
@fret What is the reason I should avoid calling a function?
– ubadub
Nov 13 '18 at 4:58
@fret What is the reason I should avoid calling a function?
– ubadub
Nov 13 '18 at 4:58
1
1
@ubadub function call is not free, and said function have a branch inside it. If target CPU don't have branch prediction - that will not be great to call it too many times in a loop (e.g. iterating through entire image). Not terrible, but you can do better without extra function call or braches.
– keltar
Nov 13 '18 at 8:59
@ubadub function call is not free, and said function have a branch inside it. If target CPU don't have branch prediction - that will not be great to call it too many times in a loop (e.g. iterating through entire image). Not terrible, but you can do better without extra function call or braches.
– keltar
Nov 13 '18 at 8:59
1
1
@keltar never mind, I got it. Leaving it here for anyone else who needs it:
(pixel & image_surface_->format->Rmask) >> image_surface_->format->Rshift;
– ubadub
Nov 14 '18 at 16:43
@keltar never mind, I got it. Leaving it here for anyone else who needs it:
(pixel & image_surface_->format->Rmask) >> image_surface_->format->Rshift;
– ubadub
Nov 14 '18 at 16:43
1
1
Also, this code is wrong. You should always use
surface->pitch
instead of width for calculating which row you are on. Even then this of course will be broken if you ever need to use it for a non 32 bit surface. Another reason to just do it the right way so you aren't needlessly shackled to specific formats.– Brad Allred
Nov 15 '18 at 23:23
Also, this code is wrong. You should always use
surface->pitch
instead of width for calculating which row you are on. Even then this of course will be broken if you ever need to use it for a non 32 bit surface. Another reason to just do it the right way so you aren't needlessly shackled to specific formats.– Brad Allred
Nov 15 '18 at 23:23
|
show 5 more comments
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53273340%2fefficiency-of-querying-an-sdl-surface-for-pixel-colors%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53273340%2fefficiency-of-querying-an-sdl-surface-for-pixel-colors%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
It is indeed O(1) but I wouldn't be using functions lie SDL_GetRGB if you can avoid it. Per pixel inner loop stuff is best done without calling a function or needing an if statement (ie branching). You can make the "pixel" pointer uint8_t* so that you can address the individual rgb components like pixel[RED_OFFSET], pixel[BLUE_OFFSET] for example.
– fret
Nov 13 '18 at 3:35
@fret What is the reason I should avoid calling a function?
– ubadub
Nov 13 '18 at 4:58
1
@ubadub function call is not free, and said function have a branch inside it. If target CPU don't have branch prediction - that will not be great to call it too many times in a loop (e.g. iterating through entire image). Not terrible, but you can do better without extra function call or braches.
– keltar
Nov 13 '18 at 8:59
1
@keltar never mind, I got it. Leaving it here for anyone else who needs it:
(pixel & image_surface_->format->Rmask) >> image_surface_->format->Rshift;
– ubadub
Nov 14 '18 at 16:43
1
Also, this code is wrong. You should always use
surface->pitch
instead of width for calculating which row you are on. Even then this of course will be broken if you ever need to use it for a non 32 bit surface. Another reason to just do it the right way so you aren't needlessly shackled to specific formats.– Brad Allred
Nov 15 '18 at 23:23